home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianColors.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  191KB  |  8,012 lines

  1. /*ScianColors.c
  2.   Color management routines for scian
  3.   Eric Pepke
  4.   March 15, 1990
  5.  
  6. */
  7.  
  8. #include "Scian.h"
  9. #include "ScianTypes.h"
  10. #include "ScianIDs.h"
  11. #include "ScianArrays.h"
  12. #include "ScianWindows.h"
  13. #include "ScianObjWindows.h"
  14. #include "ScianButtons.h"
  15. #include "ScianColors.h"
  16. #include "ScianEvents.h"
  17. #include "ScianErrors.h"
  18. #include "ScianScripts.h"
  19. #include "ScianPictures.h"
  20. #include "ScianControls.h"
  21. #include "ScianDialogs.h"
  22. #include "ScianSliders.h"
  23. #include "ScianDatasets.h"
  24. #include "ScianStyle.h"
  25. #include "ScianTitleBoxes.h"
  26. #include "ScianTextBoxes.h"
  27. #include "ScianLists.h"
  28. #include "ScianMethods.h"
  29. #include "ScianDraw.h"
  30. #include "ScianIcons.h"
  31. #include "ScianFiles.h"
  32. #include "ScianVisWindows.h"
  33. #include "ScianObjFunctions.h"
  34. #include "ScianTemplates.h"
  35. #include "ScianTemplateHelper.h"
  36. #include "ScianSciences.h"
  37. #include "gamtables.h"
  38. #include "ScianSymbols.h"
  39. #include "ScianGarbageMan.h"
  40. #include "ScianFontSystem.h"
  41. #include "ScianDepend.h"
  42. #include "ScianHelp.h"
  43.  
  44. #ifdef GRAPHICS
  45. #ifdef NEEDSGAMMA
  46. #endif
  47.  
  48. #ifdef NEEDSGAMMA
  49. #define CVAL(k) LinToGamma[k]
  50. #else
  51. #define CVAL(k) (k)
  52. #endif
  53.  
  54. #endif
  55.  
  56. int overDraw = 0;            /*Counter for overlay drawing*/
  57. Bool overDrawMenus = false;        /*Overdraw menus*/
  58.  
  59. short curRed, curGreen, curBlue;    /*Current color components in other 
  60.                       than screen draw mode*/
  61. ObjPtr iconColorPalette;
  62.  
  63. char *spfNames[NPALETTEFUNCS] =
  64.     {
  65.     "ramp",
  66.     "reverse",
  67.     "ruffle",
  68.     "smooth",
  69.     "sharpen"
  70.     };
  71.  
  72.  
  73. char *toolNames[NPALETTETOOLS] = 
  74.     {
  75.     "free form",
  76.     "sine wave",
  77.     "triangle wave",
  78.     "sawtooth wave",
  79.     "reverse sawtooth wave",
  80.     "square wave"
  81.     };
  82.  
  83. char *componentNames[NCOLORMODELS][3] =
  84.     {
  85.     {"red", "green", "blue"},
  86.     {"\"Y\"", "\"I\"", "\"Q\""},
  87.     {"hue", "saturation", "value"},
  88.     {"hue", "lightness", "saturation"}
  89.     };
  90.  
  91. char *shortComponentNames[NCOLORMODELS][3] =
  92.     {
  93.     {"R", "G", "B"},
  94.     {"Y", "I", "Q"},
  95.     {"H", "S", "V"},
  96.     {"H", "L", "S"}
  97.     };
  98.  
  99. char *colorModelNames[NCOLORMODELS] = 
  100.     {
  101.     "RGB",
  102.     "YIQ",
  103.     "HSV",
  104.     "HLS"
  105.     };
  106.  
  107. NameTyp colorModelMethods[NCOLORMODELS] = 
  108.     {
  109.     TORGB,
  110.     TOYIQ,
  111.     TOHSV,
  112.     TOHLS
  113.     };
  114.  
  115. real RGB2YIQMat[3][3] =
  116.     {{ 0.30,  0.59,  0.11},
  117.      { 0.60, -0.28, -0.32},
  118.      { 0.21, -0.52,  0.31}};
  119.  
  120. real YIQ2RGBMat[3][3] = 
  121.     {{ 1.0000,  0.9483,  0.6240},
  122.      { 1.0000, -0.2761, -0.6398},
  123.      { 1.0000, -1.1055,  1.7299}};
  124.  
  125. int paletteSerialNum = 0;        /*Serial num for palettes*/
  126.  
  127. static int ColorToPixel(ObjPtr, int);
  128. static int PixelToColor(ObjPtr, int);
  129. static int AllocColors(int);
  130.  
  131. typedef struct cr
  132.     {
  133.     struct cr *next;    /*Next color range*/
  134.     int beg, end;        /*Beginning and end (+ 1)*/
  135.     } ColorRange;
  136.  
  137. ColorRange *colorRanges;    /*The available color ranges*/
  138.  
  139. PPtr activePalettes = 0;    /*The active palettes*/
  140.  
  141. #define COLORWHEELBORDER     6    /*Border around HS control*/
  142. #define COLORWHEELSPOTSIZE    4    /*Size of spot in HS control*/
  143.  
  144. int curUIColorIndex;            /*Global current color index*/
  145. short uiColors[NUICOLORS][3];        /*Components for the UI colors*/
  146. int uiColorIndex[NUICOLORS];        /*Indices for ui colors*/
  147. short3 *colorsToScavenge;        /*Colors to scavenge*/
  148. int nScavengeColors = 0;        /*Number of colors for scavenging*/
  149.  
  150. int curNColors;                /*Current number of colors*/
  151. real curMin, curMax;            /*Current min and max values*/
  152. int curBeg;
  153. real diffMult;                /*Amount to multiply to get difference*/
  154. short3 *curColors;
  155.  
  156. ObjPtr paletteClass;            /*Class for a color palette*/
  157. ObjPtr paletteDisplayClass;        /*Class for a palette display*/
  158. ObjPtr colorControlClass;
  159. ObjPtr colorWheelClass;
  160. ObjPtr colorBarClass;
  161. #define COLORFAILTIMEOUT    60    /*Color failure timeout in seconds*/
  162. long colorFailTime = 0;            /*Time of last color failure*/
  163.  
  164. #define COLORWHEELHEIGHT    4    /*Height of a color wheel*/
  165.  
  166. #ifdef PROTO
  167. static void SetColorComponent(ObjPtr palette, int whichColor, int comp, int cc);
  168. static int GetColorComponent(ObjPtr palette, int whichColor, int comp);
  169. #endif
  170.  
  171. static short o1r, o1g, o1b;
  172. static short o2r, o2g, o2b;
  173. static short o3r, o3g, o3b;
  174.  
  175. #ifdef PROTO
  176. void OverDraw(Bool whether)
  177. #else
  178. void OverDraw(whether)
  179. Bool whether;
  180. #endif
  181. /*Sets system into overlay drawing mode, or not*/
  182. {
  183.     if (nOverDrawPlanes < 1)
  184.     {
  185.     ReportError("OverDraw", "No overlay drawing!");
  186.     return;
  187.     }
  188.  
  189. #ifdef GRAPHICS
  190.     if (whether)
  191.     {
  192.     if (!overDraw++)
  193.     {
  194.         pushattributes();
  195.         drawmode(pupForOverDraw ? PUPDRAW : OVERDRAW);
  196.         getmcolor(UIOVERRED, &o1r, &o1g, &o1b);
  197.         mapcolor(UIOVERRED, 255, 0, 0);
  198.         color(1);
  199.     }
  200.     }
  201.     else
  202.     {
  203.     if (0 == --overDraw)
  204.     {
  205.         mapcolor(UIOVERRED, o1r, o1g, o1b);
  206.         drawmode(NORMALDRAW);
  207.         popattributes();
  208.     }
  209.     }
  210. #endif
  211. }
  212.  
  213. #ifdef PROTO
  214. void OverDrawMenus(Bool whether)
  215. #else
  216. void OverDrawMenus(whether)
  217. Bool whether;
  218. #endif
  219. /*Sets system into menu overlay drawing mode, or not*/
  220. {
  221.     if (nOverDrawPlanes < 2)
  222.     {
  223.     ReportError("OverDrawMenus", "No overlay drawing!");
  224.     return;
  225.     }
  226.  
  227. #ifdef GRAPHICS
  228.     if (whether)
  229.     {
  230.     if (!overDraw++)
  231.     {
  232.         pushattributes();
  233.         drawmode(pupForOverDraw ? PUPDRAW : OVERDRAW);
  234.         getmcolor(UIOVERBLACK, &o1r, &o1g, &o1b);
  235.         mapcolor(UIOVERBLACK, 0, 0, 0);
  236.         getmcolor(UIOVERGRAY, &o2r, &o2g, &o2b);
  237.         mapcolor(UIOVERGRAY, CVAL(128), CVAL(128), CVAL(128));
  238.         getmcolor(UIOVERWHITE, &o3r, &o3g, &o3b);
  239.         mapcolor(UIOVERWHITE, 255, 255, 255);
  240.         color(1);
  241.         overDrawMenus = true;
  242.     }
  243.     }
  244.     else
  245.     {
  246.     if (0 == --overDraw)
  247.     {
  248.         mapcolor(UIOVERRED, o1r, o1g, o1b);
  249.         drawmode(NORMALDRAW);
  250.         popattributes();
  251.         overDrawMenus = false;
  252.     }
  253.     }
  254. #endif
  255. }
  256.  
  257. #ifdef PROTO
  258. void MapPalette(ObjPtr p)
  259. #else
  260. void MapPalette(p)
  261. ObjPtr p;
  262. #endif
  263. /*Maps palette p*/
  264.  
  265. {
  266. #ifdef GRAPHICS
  267.     int k, nColors;
  268.     ObjPtr var;
  269.     short3 *colors;
  270.     int beg;
  271.  
  272.     if (hasCmap == false) return;
  273.     var = GetVar(p, BEGCOLOR);
  274.     if (!var) return;
  275.     beg = GetInt(var);
  276.  
  277.     var = GetIntVar("MapPalette", p, NCOLORS);
  278.     if (!var) return;
  279.     nColors = GetInt(var);
  280.  
  281.     MakeVar(p, COLORS);
  282.     var = GetVar(p, COLORS);
  283.     if (!var) return;
  284.     colors = ELEMENTS(var);
  285.  
  286.     for (k = 0; k < nColors; ++k)
  287.     {
  288.     mapcolor(beg + k,
  289.          colors[k][0],
  290.          colors[k][1],
  291.          colors[k][2]);
  292.     TinyDelay();
  293.     }
  294. #endif
  295. }
  296.  
  297. #ifdef PROTO
  298. void MapPaletteColors(ObjPtr p, int start, int end)
  299. #else
  300. void MapPaletteColors(p, start, end)
  301. ObjPtr p; int start; int end;
  302. #endif
  303. /*Maps color from start to end in palette p*/
  304. {
  305. #ifdef GRAPHICS
  306.     int k, nColors;
  307.     ObjPtr var;
  308.     short3 *colors;
  309.     int beg;
  310.  
  311.     MakeVar(p, COLORS);
  312.     var = GetVar(p, COLORS);
  313.     if (!var) return;
  314.     colors = ELEMENTS(var);
  315.  
  316.     var = GetIntVar("MapPaletteColors", p, NCOLORS);
  317.     if (!var) return;
  318.     nColors = GetInt(var);
  319.  
  320.     if (!hasCmap) return;
  321.     var = GetVar(p, BEGCOLOR);
  322.     if (!var) return;
  323.     beg = GetInt(var);
  324.     for (k = start; k < MIN(nColors, end + 1); ++k)
  325.     {
  326.     mapcolor(beg + k,
  327.          colors[k][0],
  328.          colors[k][1],
  329.          colors[k][2]);
  330.     TinyDelay();
  331.     }
  332. #endif
  333. }
  334.  
  335. #ifdef PROTO
  336. void CopyColorsToComponents(ObjPtr p)
  337. #else
  338. void CopyColorsToComponents(p)
  339. ObjPtr p;
  340. #endif
  341. /*Copies the colors to components based on color model*/
  342. {
  343.     ObjPtr var;
  344.     int cm, k;
  345.     short3 *colors, *components;
  346.     real r, g, b, h, s, v, l, y, i, q;
  347.     long dims[2];
  348.  
  349.     var = GetIntVar("CopyColorsToComponents", p, COLORMODEL);
  350.     if (var)
  351.     {
  352.     cm = GetInt(var);
  353.     }
  354.     else
  355.     {
  356.     cm = CM_RGB;
  357.     }
  358.  
  359.     MakeVar(p, COLORS);
  360.     var = GetVar(p, COLORS);
  361.     if (!var) return;
  362.     colors = ELEMENTS(var);
  363.  
  364.     dims[0] = DIMS(var)[0];
  365.     dims[1] = 3;
  366.     var = NewArray(AT_SHORT, 2, dims);
  367.     if (!var) return;
  368.     components = ELEMENTS(var);
  369.     SetVar(p, COLORCOMP, var);
  370.  
  371.     for (k = 0; k < dims[0]; ++k)
  372.     {
  373.     switch (cm)
  374.     {
  375.         case CM_RGB:
  376.         components[k][0] = colors[k][0];
  377.         components[k][1] = colors[k][1];
  378.         components[k][2] = colors[k][2];
  379.         break;
  380.         case CM_HSV:
  381.         r = ((real) colors[k][0]) / 255.0;
  382.         g = ((real) colors[k][1]) / 255.0;
  383.         b = ((real) colors[k][2]) / 255.0;
  384.  
  385.         RGB2HSV(&h, &s, &v, r, g, b);
  386.  
  387.         components[k][0] = h * 255.0 + 0.5;
  388.         components[k][1] = s * 255.0 + 0.5;
  389.         components[k][2] = v * 255.0 + 0.5;
  390.         break;
  391.         case CM_HLS:
  392.         r = ((real) colors[k][0]) / 255.0;
  393.         g = ((real) colors[k][1]) / 255.0;
  394.         b = ((real) colors[k][2]) / 255.0;
  395.  
  396.         RGB2HLS(&h, &l, &s, r, g, b);
  397.  
  398.         components[k][0] = h * 255.0 + 0.5;
  399.         components[k][1] = l * 255.0 + 0.5;
  400.         components[k][2] = s * 255.0 + 0.5;
  401.         break;
  402.         case CM_YIQ:
  403.         r = ((real) colors[k][0]) / 255.0;
  404.         g = ((real) colors[k][1]) / 255.0;
  405.         b = ((real) colors[k][2]) / 255.0;
  406.  
  407.         RGB2YIQ(&y, &i, &q, r, g, b);
  408.  
  409.         components[k][0] = y * 255.0 + 0.5;
  410.         components[k][1] = i * 255.0 + 0.5;
  411.         components[k][2] = q * 255.0 + 0.5;
  412.         break;
  413.         default:
  414.         components[k][0] = colors[k][0];
  415.         components[k][1] = colors[k][1];
  416.         components[k][2] = colors[k][2];
  417.         break;
  418.     }
  419.     }
  420. }
  421.  
  422. #ifdef PROTO
  423. void CopyComponentsToColors(ObjPtr p)
  424. #else
  425. void CopyComponentsToColors(p)
  426. ObjPtr p;
  427. #endif
  428. /*Copies the colors to components based on color model*/
  429. {
  430.     ObjPtr var;
  431.     int cm, k;
  432.     short3 *colors, *components;
  433.     long dimensions[2];
  434.     real r, g, b, h, s, v, l, y, i, q; 
  435.  
  436.     var = GetIntVar("CopyComponentsToColors", p, COLORMODEL);
  437.     if (var)
  438.     {
  439.     cm = GetInt(var);
  440.     }
  441.     else
  442.     {
  443.     cm = CM_RGB;
  444.     }
  445.  
  446.     var = GetVar(p, COLORCOMP);
  447.     if (!var) return;
  448.     components = ELEMENTS(var);
  449.  
  450.     dimensions[0] = DIMS(var)[0];
  451.     dimensions[1] = 3;
  452.     var = NewArray(AT_SHORT, 2, dimensions);
  453.     if (!var) return;
  454.     colors = ELEMENTS(var);
  455.     SetVar(p, COLORS, var);
  456.  
  457.     for (k = 0; k < dimensions[0]; ++k)
  458.     {
  459.     switch (cm)
  460.     {
  461.         case CM_RGB:
  462.         colors[k][0] = components[k][0];
  463.         colors[k][1] = components[k][1];
  464.         colors[k][2] = components[k][2];
  465.         break;
  466.         case CM_HSV:
  467.         h = ((real) components[k][0]) / 255.0;
  468.         s = ((real) components[k][1]) / 255.0;
  469.         v = ((real) components[k][2]) / 255.0;
  470.  
  471.         HSV2RGB(&r, &g, &b, h, s, v);
  472.  
  473.         colors[k][0] = r * 255.0 + 0.5;
  474.         colors[k][1] = g * 255.0 + 0.5;
  475.         colors[k][2] = b * 255.0 + 0.5;
  476.         break;
  477.         case CM_HLS:
  478.         h = ((real) components[k][0]) / 255.0;
  479.         l = ((real) components[k][1]) / 255.0;
  480.         s = ((real) components[k][2]) / 255.0;
  481.  
  482.         HLS2RGB(&r, &g, &b, h, l, s);
  483.  
  484.         colors[k][0] = r * 255.0 + 0.5;
  485.         colors[k][1] = g * 255.0 + 0.5;
  486.         colors[k][2] = b * 255.0 + 0.5;
  487.         break;
  488.         case CM_YIQ:
  489.         y = ((real) components[k][0]) / 255.0;
  490.         i = ((real) components[k][1]) / 255.0;
  491.         q = ((real) components[k][2]) / 255.0;
  492.  
  493.         YIQ2RGB(&r, &g, &b, y, i, q);
  494.  
  495.         colors[k][0] = r * 255.0 + 0.5;
  496.         colors[k][1] = g * 255.0 + 0.5;
  497.         colors[k][2] = b * 255.0 + 0.5;
  498.         break;
  499.         default:
  500.         components[k][0] = colors[k][0];
  501.         components[k][1] = colors[k][1];
  502.         components[k][2] = colors[k][2];
  503.         break;
  504.     }
  505.     }
  506. }
  507.  
  508. #ifdef PROTO
  509. void CopyColorsToPalette(ObjPtr p, short3 *colors)
  510. #else
  511. void CopyColorsToPalette(p, colors)
  512. ObjPtr p;
  513. short3 *colors;
  514. #endif
  515. /*Copies the colors into palette p*/
  516. {
  517.     int k, nColors;
  518.     ObjPtr var;
  519.     long dims[2];
  520.     short3 *newColors;
  521.  
  522.     var = GetIntVar("CopyColorsToPalette", p, NCOLORS);
  523.     if (!var) return;
  524.     nColors = GetInt(var);
  525.  
  526.     dims[0] = nColors;
  527.     dims[1] = 3;
  528.     var = NewArray(AT_SHORT, 2, dims);
  529.     SetVar(p, COLORS, var);
  530.     newColors = ELEMENTS(var);
  531.  
  532.     for (k = 0; k < nColors; ++k)
  533.     {
  534.     newColors[k][0] = colors[k][0];
  535.     newColors[k][1] = colors[k][1];
  536.     newColors[k][2] = colors[k][2];
  537.     }
  538.     CopyColorsToComponents(p);
  539. }
  540.  
  541. #ifdef PROTO
  542. void FieldPaletteName(ObjPtr palette, ObjPtr field)
  543. #else
  544. void FieldPaletteName(palette, field)
  545. ObjPtr palette, field;
  546. #endif
  547. /*Names a palette based on a field*/
  548. {
  549.     ObjPtr name;
  550.  
  551.     MakeVar(field, NAME);
  552.     name = GetStringVar("FieldPaletteName", field, NAME);
  553.  
  554.     if (!name)
  555.     {
  556.     return;
  557.     }
  558.  
  559.     strcpy(tempStr, GetString(name));
  560.     strcat(tempStr, " Palette");
  561.     SetVar(palette, NAME, NewString(tempStr));
  562. }
  563.  
  564. ObjPtr MakePaletteName(palette)
  565. ObjPtr palette;
  566. /*Makes a name for a palette*/
  567. {
  568.     if (GetVar(palette, NAME))
  569.     {
  570.     return ObjFalse;
  571.     }
  572.     else
  573.     {
  574.     sprintf(tempStr, "Palette %ld", ++paletteSerialNum);
  575.     SetVar(palette, NAME, NewString(tempStr));
  576.     return ObjTrue;
  577.     }
  578. }
  579.  
  580. void AlertColorFailure()
  581. /*Alerts the user that a color allocation has failed*/
  582. {
  583.     WinInfoPtr errWindow;
  584.  
  585.     if (runningScript)
  586.     {
  587.     fprintf(stderr, "SciAn has run out of color table entries.  It will continue to try to find enough \
  588. colors to run normally.  Until it does, you may see some unusual colors in \
  589. some windows.");
  590.     }
  591.     else
  592.     {
  593.     errWindow = AlertUser(UICAUTIONALERT, (WinInfoPtr) 0,
  594.     "SciAn has run out of color table entries.  It will continue to try to find enough \
  595. colors to run normally.  Until it does, you may see some unusual colors in \
  596. some windows.",
  597.         0, 0, "Oh well");
  598.     SetVar((ObjPtr) errWindow, HELPSTRING,
  599.         NewString("All the windows of SciAn, as well as the windows of other \
  600. processes, share the same color table.  When there are several visualizations \
  601. on the screen, SciAn must share the color table between windows.  It tries to \
  602. allocate and deallocate chunks of the color table according to need, but \
  603. sometimes the number of visualizations grows so large that there are simply not \
  604. enough colors to go around.\n\
  605. \n\
  606. SciAn will continue to try to allocate colors.  You can reduce the number of \
  607. colors you are using by a number of ways.  If your computer can do 24-bit RGB, \
  608. you can set some of the visualization windows to Full Color by clicking on the \
  609. Full Color button at the bottom right of the visualization window.  You can close \
  610. visualization windows that you are not using.  You can color some of the \
  611. visualizations white or increase visualizations colored by datasets to full \
  612. brightness."));
  613.     SetVar((ObjPtr) errWindow, INHIBITLOGGING, ObjTrue);
  614.     }
  615. }
  616.  
  617. #ifdef PROTO
  618. void SetPalette(ObjPtr p)
  619. #else
  620. void SetPalette(p)
  621. ObjPtr p;
  622. #endif
  623. /*Sets the current palette to p*/
  624. {
  625.     ObjPtr var;
  626.     int nColors;
  627.     int beg;
  628.  
  629.     var = GetIntVar("SetPalette", p, NCOLORS);
  630.     if (!var) return;
  631.     nColors = GetInt(var);
  632.     curNColors = nColors;
  633.  
  634.     MakeVar(p, MINMAX);
  635.     var = GetFixedArrayVar("SetPalette", p, MINMAX, 1, 2L);
  636.     if (!var)
  637.     {
  638.     return;
  639.     }
  640.     curMin = ((real *) ELEMENTS(var))[0];
  641.     curMax = ((real *) ELEMENTS(var))[1];
  642.  
  643. #ifdef GRAPHICS
  644.     if ((!(var = GetVar(p, BEGCOLOR))) && (!rgbp))
  645.     {
  646.     /*Allocate some colors on demand*/
  647.     beg = AllocColors(curNColors);
  648.     if (beg >= 0)
  649.     {
  650.         /*Allocation succeeded*/
  651.         SetVar(p, BEGCOLOR, NewInt(beg));
  652.         MapPalette(p);
  653.         curBeg = beg + 2;
  654.     }
  655.     else
  656.     {
  657.         /*Allocation failed*/
  658.         struct tms buffer;
  659.         long curTime;
  660.  
  661.         curTime = times(&buffer) / HEARTBEAT;
  662.  
  663.         if (curTime > colorFailTime + COLORFAILTIMEOUT)
  664.         {
  665.         colorFailTime = curTime;
  666.         DoUniqueTask(AlertColorFailure);
  667.         }
  668.         curNColors = uiColorIndex[UIWHITE] -
  669.              uiColorIndex[UIBLACK];
  670.         curBeg = uiColorIndex[UIBLACK];
  671.     }
  672.     }
  673.     else
  674. #endif
  675.     {
  676.     curBeg = GetInt(var) + 2;
  677.     }
  678.  
  679.     MakeVar(p, COLORS);
  680.     var = GetVar(p, COLORS);
  681.     if (!var)
  682.     {
  683.     return;
  684.     }
  685.     curColors = ((short3 *) ELEMENTS(var)) + 2;
  686.  
  687.     diffMult = ((real) curNColors - 4) / (curMax - curMin);
  688. }
  689.  
  690. #ifdef PROTO
  691. void SetPaletteMinMax(ObjPtr p, real min, real max)
  692. #else
  693. void SetPaletteMinMax(p, min, max)
  694. ObjPtr p;
  695. real min, max;
  696. #endif
  697. /*Sets the min and max of palette p to min and max*/
  698. {
  699.     ObjPtr var;
  700.     var = NewRealArray(1, 2L);
  701.     ((real *) ELEMENTS(var))[0] = min;
  702.     ((real *) ELEMENTS(var))[1] = max;
  703.     SetVar(p, MINMAX, var);
  704.     SetVar(p, CHANGED, ObjTrue);
  705. }
  706.  
  707. #ifdef PROTO
  708. static void CompactColors(void)
  709. #else
  710. static void CompactColors()
  711. #endif
  712. /*Compacts all the colors*/
  713. {
  714.     ColorRange *runner;
  715.  
  716.     if (colorRanges == 0)
  717.     {
  718.     ReportError("CompactColors", "No color ranges");
  719.     return;
  720.     }
  721.  
  722.     runner = colorRanges;
  723.     while (runner && runner -> next)
  724.     {
  725.     if (runner -> end >= runner -> next -> beg)
  726.     {
  727.         /*Compact two adjacent colors*/
  728.         ColorRange *next;
  729.  
  730.         runner -> end = runner -> next -> end;
  731.         next = runner -> next -> next;
  732.         Free(runner -> next);
  733.         runner -> next = next;
  734.     }
  735.     else
  736.     {
  737.         runner = runner -> next;
  738.     }
  739.     }
  740. }
  741.  
  742. #ifdef PROTO
  743. static int AllocColors(int n)
  744. #else
  745. static int AllocColors(n)
  746. int n;
  747. #endif
  748. /*Allocates n contiguous colors, returns their start or -1*/
  749. {
  750.     ColorRange **runner, **bestFit;
  751.     int fit;            /*Fit of best fit so far*/
  752.  
  753.     if (colorRanges == 0)
  754.     {
  755.     ReportError("AllocColors", "No color ranges");
  756.     return -1;
  757.     }
  758.  
  759.     /*Compact the colors*/
  760.     CompactColors();
  761.  
  762.     /*Search for best fit*/
  763.     fit = 32767;
  764.     bestFit = (ColorRange **) 0;
  765.     runner = &colorRanges;
  766.  
  767.     while (*runner)
  768.     {
  769.     int nAvailable;
  770.     nAvailable = (*runner) -> end - (*runner) -> beg;
  771.     if (nAvailable >= n)
  772.     {
  773.         if (nAvailable - n < fit)
  774.         {
  775.         fit = nAvailable - n;
  776.         bestFit = runner;
  777.         }
  778.     }
  779.     runner = &((*runner) -> next);
  780.     }
  781.  
  782.     if (bestFit)
  783.     {
  784.     int retVal;
  785.     retVal = (*bestFit) -> beg;
  786.  
  787.     if (fit == 0)
  788.     {
  789.         /*Must delete this fit*/
  790.         ColorRange *thisFit;
  791.         thisFit = (*bestFit);
  792.         Free(thisFit);
  793.         (*bestFit) = (*bestFit) -> next;
  794.     }
  795.     else
  796.     {
  797.         /*Just need to adjust it*/
  798.         (*bestFit) -> beg += n;
  799.     }
  800.     return retVal;
  801.     }
  802.     else
  803.     {
  804.     /*Allocation failed*/
  805.     return -1;
  806.     }
  807. }
  808.  
  809. #ifdef PROTO
  810. static void FreeColors(int start, int n)
  811. #else
  812. static void FreeColors(start, n)
  813. int start, n;
  814. #endif
  815. /*Frees n contiguous colors at start*/
  816. {
  817.     ColorRange **runner, *next;
  818.  
  819.     if (colorRanges == 0)
  820.     {
  821.     ReportError("FreeColors", "No color ranges");
  822.     return;
  823.     }
  824.  
  825.     /*Add a new color range at the appropriate point*/
  826.     runner = &colorRanges;
  827.  
  828.     while (*runner && (*runner) -> beg < start + n)
  829.     {
  830.     runner = &((*runner) -> next);
  831.     }
  832.     next = *runner;
  833.     *runner = newp(ColorRange);
  834.     (*runner) -> beg = start;
  835.     (*runner) -> end = start + n;
  836.     (*runner) -> next = next;
  837. }
  838.  
  839. #ifdef PROTO
  840. static void MakeUIColor(int whichColor, short r, short g, short b)
  841. #else
  842. static void MakeUIColor(whichColor, r, g, b)
  843. int whichColor;
  844. short r, g, b;
  845. #endif
  846. /*Makes UI color whichColor to r, g, b*/
  847. {
  848. #ifdef GRAPHICS
  849.     r = CVAL(r);
  850.     g = CVAL(g);
  851.     b = CVAL(b);
  852.  
  853.     /*Search the existing colors for the best match.*/
  854.     if (hasCmap && scavengeColors)
  855.     {
  856.     short bestR, bestG, bestB;
  857.     int bestC;
  858.     short testR, testG, testB;
  859.     int testC;
  860.     int bestDist = MAXCDIST + 1;
  861.     int testDist;
  862.  
  863.     for (testC = 0; testC < nScavengeColors; ++testC)
  864.     {
  865.         if (testC < 16 || testC >= 32)
  866.         {
  867.         /*Colors between 16 and 32 unreliable*/
  868.         testR = colorsToScavenge[testC][0];
  869.         testG = colorsToScavenge[testC][1];
  870.         testB = colorsToScavenge[testC][2];
  871.  
  872.         testDist = MAX(ABS(testR - r), MAX(ABS(testG - g), ABS(testB - b)));
  873.         if (testDist <= bestDist) /*Change to < for first not last*/
  874.         {
  875.         if ((r == g) && (g == b))
  876.         {
  877.             /*Test for gray dirtiness failure*/
  878.             if (MAX(testR, MAX(testG, testB)) -
  879.             MIN(testR, MIN(testG, testB))
  880.             > MAXGRAYDIRT)
  881.             {
  882.             /*Disallow this one and continue search*/
  883.             continue;
  884.             }
  885.         }
  886.         bestDist = testDist;
  887.         bestR = testR;
  888.         bestG = testG;
  889.         bestB = testB;
  890.         bestC = testC;
  891.         }
  892.         }
  893.     }
  894.  
  895.     /*Now see if it's good enough*/
  896.     if (bestDist <= MAXCDIST)
  897.     {
  898.         /*It's OK, use this one*/
  899.         if (showConfig)
  900.         {
  901.         printf("Best match to UI color %d (%d %d %d) found at %d (%d %d %d)\n",
  902.             whichColor, r, g, b, (int) bestC, (int) bestR, (int) bestG, (int) bestB);
  903.         }
  904.         uiColorIndex[whichColor] = bestC;
  905.     }
  906.     else
  907.     {
  908.         /*No good, allocate one*/
  909.         if (hasCmap)
  910.         {
  911.         if (showConfig)
  912.         {
  913.             printf("UI Color %d (%d %d %d) failed color scavenge search.  Allocated at %d.\n",
  914.             whichColor, r, g, b, curUIColorIndex);
  915.         }
  916.         uiColorIndex[whichColor] = curUIColorIndex++;
  917.         mapcolor(uiColorIndex[whichColor], r, g, b);
  918.         TinyDelay();
  919.         }
  920.         else
  921.         {
  922.         uiColorIndex[whichColor] = -1;
  923.         if (showConfig)
  924.         {
  925.             printf("UI Color %d (%d %d %d) failed color scavenge search.  Not allocated.\n",
  926.             whichColor, r, g, b);
  927.         }
  928.         }
  929.     }
  930.     }
  931.     else
  932.     {
  933.     /*Just use the next value in the color map*/
  934.     if (hasCmap)
  935.     {
  936.     if (showConfig)
  937.     {
  938.         printf("UI Color %d (%d %d %d) allocated at %d.\n",
  939.             whichColor, r, g, b, curUIColorIndex);
  940.     }
  941.     uiColorIndex[whichColor] = curUIColorIndex++;
  942.     if (hasCmap)
  943.     {
  944.         mapcolor(uiColorIndex[whichColor], r, g, b);
  945.         TinyDelay();
  946.     }
  947.     }
  948.     else
  949.     {
  950.     if (showConfig)
  951.     {
  952.         printf("UI Color %d (%d %d %d) not allocated because it's always RGB.\n",
  953.             whichColor, r, g, b);
  954.     }
  955.     uiColorIndex[whichColor] = -1;
  956.     }
  957.     }
  958.  
  959.     uiColors[whichColor][0] = r;
  960.     uiColors[whichColor][1] = g;
  961.     uiColors[whichColor][2] = b;
  962. #endif
  963. }
  964.  
  965. #ifdef PROTO
  966. int ClosestUIColor(float clr[3])
  967. #else
  968. int ClosestUIColor(clr)
  969. float clr[3];
  970. #endif
  971. /*Returns the closest UI color to clr*/
  972. {
  973.     int k;
  974.     short r, g, b;
  975.     short bestError;
  976.     short best;
  977.     r = clr[0] * 256.0;
  978.     g = clr[1] * 256.0;
  979.     b = clr[2] * 256.0;
  980.  
  981.     bestError = 5000;    /*Big*/
  982.     for (k = 0; k < NUICOLORS; ++k)
  983.     {
  984.     short error;
  985.     error = ABS(uiColors[k][0] - r) +
  986.             ABS(uiColors[k][1] - g) +
  987.             ABS(uiColors[k][2] - b);
  988.     if (error < bestError)
  989.     {
  990.         bestError = error;
  991.         best = k;
  992.     }
  993.     }
  994.     return best;
  995. }
  996.  
  997. static ObjPtr DrawColorWheel(object)
  998. ObjPtr object;
  999. /*Draws an HS control*/
  1000. {
  1001. #ifdef GRAPHICS
  1002.     int left, right, bottom, top;
  1003.     int cx, cy;
  1004.     int width, height, radius;
  1005.     ObjPtr backColor;            /*Color of the background*/
  1006.     FuncTyp drawContents;        /*Routine to draw the contents*/
  1007.     ObjPtr valueArray;
  1008.     real value[2];
  1009.  
  1010.     Get2DIntBounds(object, &left, &right, &bottom, &top);
  1011.  
  1012.     /*Draw the control frame*/
  1013.     DrawRaisedRect(left, right, bottom, top, UIGRAY50);
  1014.  
  1015.     /*Draw the color background*/
  1016.     cx = (left + right) / 2;
  1017.     cy = (bottom + top) / 2;
  1018.     width = right - left;
  1019.     height = top - bottom;
  1020.     
  1021.     if (width > height)
  1022.     {
  1023.     radius = height / 2 - COLORWHEELBORDER;
  1024.     }
  1025.     else
  1026.     {
  1027.     radius = width / 2 - COLORWHEELBORDER;
  1028.     }
  1029.  
  1030.     /*Draw the color wedges*/
  1031.     FillUIWedge(cx, cy, radius, -30, 30, UIRED);
  1032.     FillUIWedge(cx, cy, radius, 30, 90, UIYELLOW);
  1033.     FillUIWedge(cx, cy, radius, 90, 150, UIGREEN);
  1034.     FillUIWedge(cx, cy, radius, 150, 210, UICYAN);
  1035.     FillUIWedge(cx, cy, radius, 210, 270, UIBLUE);
  1036.     FillUIWedge(cx, cy, radius, 270, 330, UIMAGENTA);
  1037.     FillUIGauzeDisc(cx, cy, (int) radius * 2 / 3, UIWHITE);
  1038.     FillUIDisc(cx, cy, (int) radius / 3, UIWHITE);
  1039.  
  1040.     /*Draw the spot*/
  1041.     valueArray = GetVar(object, VALUE);
  1042.     if (valueArray)
  1043.     { 
  1044.     Array2CArray(value, valueArray);
  1045.  
  1046.     SetUIColor(UIBLACK);
  1047.     cx += radius * value[1] * rcos(2.0 * M_PI * value[0]);
  1048.     cy += radius * value[1] * rsin(2.0 * M_PI * value[0]);
  1049.     DrawUILine(cx - COLORWHEELSPOTSIZE, cy, cx + COLORWHEELSPOTSIZE, cy, UIBLACK);
  1050.     DrawUILine(cx, cy - COLORWHEELSPOTSIZE, cx, cy + COLORWHEELSPOTSIZE, UIBLACK);
  1051.     }
  1052.  
  1053.     if (!GetPredicate(object, ACTIVATED))
  1054.     {
  1055.     FillUIGauzeRect(left, right, bottom, top, UIBACKGROUND);
  1056.     }
  1057. #endif
  1058.     return ObjTrue;
  1059. }
  1060.  
  1061. #ifdef PROTO
  1062. void RGB2YIQ(real *y, real *i, real*q, real r, real g, real b)
  1063. #else
  1064. void RGB2YIQ(y, i, q, r, g, b)
  1065. real *y, *i, *q, r, g, b;
  1066. #endif
  1067. /*Converts r, g, b, into y, i, q*/
  1068. {
  1069.     *y = RGB2YIQMat[0][0] * r +
  1070.      RGB2YIQMat[0][1] * g +
  1071.      RGB2YIQMat[0][2] * b; 
  1072.     *i = RGB2YIQMat[1][0] * r +
  1073.      RGB2YIQMat[1][1] * g +
  1074.      RGB2YIQMat[1][2] * b; 
  1075.     *q = RGB2YIQMat[2][0] * r +
  1076.      RGB2YIQMat[2][1] * g +
  1077.      RGB2YIQMat[2][2] * b;
  1078.  
  1079.     *i = (*i + 0.6) / 1.2;
  1080.     *q = (*q + 0.52) / 1.04;
  1081.  
  1082.     if (*y < 0.0) *y = 0.0;
  1083.     if (*y > 1.0) *y = 1.0;
  1084.     if (*i < 0.0) *i = 0.0;
  1085.     if (*i > 1.0) *i = 1.0;
  1086.     if (*q < 0.0) *q = 0.0;
  1087.     if (*q > 1.0) *q = 1.0;
  1088. }
  1089.  
  1090. #ifdef PROTO
  1091. void YIQ2RGB(real *r, real *g, real *b, real y, real i, real q)
  1092. #else
  1093. void YIQ2RGB(r, g, b, y, i, q)
  1094. real y, i, q, *r, *g, *b;
  1095. #endif
  1096. /*Converts y, i, q, into r, g, b*/
  1097. {
  1098.     i = i * 1.2 - 0.6;
  1099.     q = q * 1.04 - 0.52;
  1100.  
  1101.     *r = YIQ2RGBMat[0][0] * y +
  1102.      YIQ2RGBMat[0][1] * i +
  1103.      YIQ2RGBMat[0][2] * q; 
  1104.     *g = YIQ2RGBMat[1][0] * y +
  1105.      YIQ2RGBMat[1][1] * i +
  1106.      YIQ2RGBMat[1][2] * q; 
  1107.     *b = YIQ2RGBMat[2][0] * y +
  1108.      YIQ2RGBMat[2][1] * i +
  1109.      YIQ2RGBMat[2][2] * q;
  1110.  
  1111.     if (*r < 0.0) *r = 0.0;
  1112.     if (*r > 1.0) *r = 1.0;
  1113.     if (*g < 0.0) *g = 0.0;
  1114.     if (*g > 1.0) *g = 1.0;
  1115.     if (*b < 0.0) *b = 0.0;
  1116.     if (*b > 1.0) *b = 1.0;
  1117. }
  1118.  
  1119. #ifdef PROTO
  1120. void HSV2RGB(real *r, real *g, real *b, real h, real s, real v)
  1121. #else
  1122. void HSV2RGB(r, g, b, h, s, v)
  1123. real *r, *g, *b, h, s, v;
  1124. #endif
  1125. /*Converts h s v into r g b.  All within range 0..1
  1126.   Adapted from Foley & VanDam*/
  1127. {
  1128.     int i;
  1129.     real f;
  1130.     real p, q, t;
  1131.  
  1132.     while (h < 0.0) h += 1.0;
  1133.     while (h > 1.0) h -= 1.0;
  1134.     h *= 6;        /*h from 0 to 6*/
  1135.     i = h;
  1136.     f = h - i;        /*fractional part of i*/
  1137.     i %= 6;        /*i from 0 to 5*/
  1138.     p = v * (1.0 - s);
  1139.     q = v * (1.0 - (s * f));
  1140.     t = v * (1.0 - (s * (1.0 - f)));
  1141.  
  1142.     switch (i)
  1143.     {
  1144.     case 0:
  1145.         *r = v;
  1146.         *g = t;
  1147.         *b = p;
  1148.         break;
  1149.     case 1:
  1150.         *r = q;
  1151.         *g = v;
  1152.         *b = p;
  1153.         break;
  1154.     case 2:
  1155.         *r = p;
  1156.         *g = v;
  1157.         *b = t;
  1158.         break;
  1159.     case 3:
  1160.         *r = p;
  1161.         *g = q;
  1162.         *b = v;
  1163.         break;
  1164.     case 4:
  1165.         *r = t;
  1166.         *g = p;
  1167.         *b = v;
  1168.         break;
  1169.     case 5:
  1170.         *r = v;
  1171.         *g = p;
  1172.         *b = q;
  1173.         break;
  1174.     }
  1175.     if (*r > 1.0) *r = 0.0; else if (*r < 0.0) *r = 0.0;
  1176.     if (*g > 1.0) *g = 0.0; else if (*g < 0.0) *g = 0.0;
  1177.     if (*b > 1.0) *b = 0.0; else if (*b < 0.0) *b = 0.0;
  1178. }
  1179.  
  1180. #ifdef PROTO
  1181. real HLSValue(real n1, real n2, real h)
  1182. #else
  1183. real HLSValue(n1, n2, h)
  1184. real n1; real n2; real h;
  1185. #endif
  1186. {
  1187.     while (h < 0.0) h += 1.0;
  1188.     while (h > 1.0) h -= 1.0;
  1189.  
  1190.     if (h < 1.0 / 6.0)
  1191.     {
  1192.     return n1 + (n2 - n1) * h * 6.0;
  1193.     }
  1194.     else if (h < 0.5)
  1195.     {
  1196.     return n2;
  1197.     }
  1198.     else if (h < 4.0 / 6.0)
  1199.     {
  1200.     return n1 + (n2 - n1) * (4.0 / 6.0 - h) * 6.0;
  1201.     }
  1202.     else
  1203.     {
  1204.     return n1;
  1205.     }
  1206. }
  1207.  
  1208. #ifdef PROTO
  1209. void HLS2RGB(real *r, real *g, real *b, real h, real l, real s)
  1210. #else
  1211. void HLS2RGB(r, g, b, h, l, s)
  1212. real *r, *g, *b, h, s, l;
  1213. #endif
  1214. /*Converts h l s into r g b.  All within range 0..1
  1215.   Adapted from Foley & VanDam*/
  1216. {
  1217.     real m1, m2;
  1218.     if (l <= 0.5)
  1219.     {
  1220.     m2 = l * (1.0 + s);
  1221.     }
  1222.     else
  1223.     {
  1224.     m2 = l + s - l * s;
  1225.     }
  1226.     m1 = 2 * l - m2;
  1227.  
  1228.     if (s == 0)
  1229.     {
  1230.     *r = *g = *b = 1.0;
  1231.     }
  1232.     else
  1233.     {
  1234.     *r = HLSValue(m1, m2, h + 1.0 / 3.0);
  1235.     *g = HLSValue(m1, m2, h);
  1236.     *b = HLSValue(m1, m2, h - 1.0 / 3.0);
  1237.     }
  1238.  
  1239.     if (*r > 1.0) *r = 0.0; else if (*r < 0.0) *r = 0.0;
  1240.     if (*g > 1.0) *g = 0.0; else if (*g < 0.0) *g = 0.0;
  1241.     if (*b > 1.0) *b = 0.0; else if (*b < 0.0) *b = 0.0;
  1242. }
  1243.  
  1244. #ifdef PROTO
  1245. void RGB2HSV(real *h, real *s, real *v, real r, real g, real b)
  1246. #else
  1247. void RGB2HSV(h, s, v, r, g, b)
  1248. real r, g, b, *h, *s, *v;
  1249. #endif
  1250. /*Converts rgb to hsv.  All numbers within range 0 to 1.*/
  1251. {
  1252.     real max, min;
  1253.  
  1254.     max = MAX(r, MAX(g, b));
  1255.     min = MIN(r, MIN(g, b));
  1256.     *v = max;
  1257.  
  1258.     if (max > 0.0)
  1259.     {
  1260.     *s = (max - min) / max;
  1261.     }
  1262.     else
  1263.     {
  1264.     *s = 0;
  1265.     }
  1266.  
  1267.     if (*s > 0.0)
  1268.     {
  1269.     real rc, gc, bc;
  1270.  
  1271.     rc = (max - r) / (max - min);
  1272.     gc = (max - g) / (max - min);
  1273.     bc = (max - b) / (max - min);
  1274.     if (r == max)
  1275.     {
  1276.         *h = (bc - gc) / 6.0;
  1277.     }
  1278.     else if (g == max)
  1279.     {
  1280.         *h = (2.0 + rc - bc) / 6.0;
  1281.     }
  1282.     else
  1283.     {
  1284.         *h = (4.0 + gc - rc) / 6.0;
  1285.     }
  1286.     }
  1287.     else
  1288.     {
  1289.     *h = 0.0;
  1290.     }
  1291.     if (*h < 0.0) *h += 1.0;
  1292. }
  1293.  
  1294. #ifdef PROTO
  1295. void RGB2HLS(real *h, real *l, real *s, real r, real g, real b)
  1296. #else
  1297. void RGB2HLS(h, l, s, r, g, b)
  1298. real r, g, b, *h, *s, *l;
  1299. #endif
  1300. /*Converts rgb to hls.  All numbers within range 0 to 1.*/
  1301. {
  1302.     real max, min;
  1303.  
  1304.     max = MAX(r, MAX(g, b));
  1305.     min = MIN(r, MIN(g, b));
  1306.     *l = (max + min) * 0.5;
  1307.  
  1308.     if (max == min)
  1309.     {
  1310.     *s = 0.0;
  1311.     *h = 0.0;
  1312.     }
  1313.     else
  1314.     {
  1315.     real rc, gc, bc;
  1316.  
  1317.     if (*l <= 0.5)
  1318.     {
  1319.         *s = (max - min) / (max + min);
  1320.     }
  1321.     else
  1322.     {
  1323.         *s = (max - min) / (2 - max - min);
  1324.     }
  1325.  
  1326.     rc = (max - r) / (max - min);
  1327.     gc = (max - g) / (max - min);
  1328.     bc = (max - b) / (max - min);
  1329.     if (r == max)
  1330.     {
  1331.         *h = (bc - gc) / 6.0;
  1332.     }
  1333.     else if (g == max)
  1334.     {
  1335.         *h = (2.0 + rc - bc) / 6.0;
  1336.     }
  1337.     else
  1338.     {
  1339.         *h = (4.0 + gc - rc) / 6.0;
  1340.     }
  1341.     }
  1342. }
  1343.  
  1344. static ObjPtr PressColorWheel(object, mouseX, mouseY, flags)
  1345. ObjPtr object;
  1346. int mouseX, mouseY;
  1347. long flags;
  1348. /*Track a click in an HS control.  Double-click snaps to closest pure hue*/
  1349. {
  1350.     int left, right, bottom, top;
  1351.     int cx, cy;
  1352.     int width, height, radius;
  1353.     ObjPtr backColor;            /*Color of the background*/
  1354.     FuncTyp drawContents;        /*Routine to draw the contents*/
  1355.     ObjPtr valueArray;
  1356.     real value[2];
  1357.     int lastX, lastY;            /*Last X and Y mouse position*/
  1358.     int sX, sY;                /*Shifted x and y for calculation*/
  1359.     Bool dontTrack;            /*True iff don't track*/
  1360.  
  1361.     Get2DIntBounds(object, &left, &right, &bottom, &top);
  1362.  
  1363.     if (mouseX < left || mouseX > right || mouseY < bottom || mouseY > top)
  1364.     {
  1365.     return ObjFalse;
  1366.     }
  1367.  
  1368.     if (TOOL(flags) == T_HELP)
  1369.     {
  1370.     ContextHelp(object);
  1371.     return ObjTrue;
  1372.     }
  1373.  
  1374.     if (!GetPredicate(object, ACTIVATED)) return ObjTrue;
  1375.  
  1376.     MakeMeCurrent(object);
  1377.  
  1378.     SaveForUndo(object);
  1379.  
  1380.     cx = (left + right) / 2;
  1381.     cy = (bottom + top) / 2;
  1382.     width = right - left;
  1383.     height = top - bottom;
  1384.     
  1385.     if (width > height)
  1386.     {
  1387.     radius = height / 2 - COLORWHEELBORDER;
  1388.     }
  1389.     else
  1390.     {
  1391.     radius = width / 2 - COLORWHEELBORDER;
  1392.     }
  1393.  
  1394.     /*Get the current value of the control*/
  1395.     valueArray = GetFixedArrayVar("PressColorWheel", object, VALUE, 1, 2L);
  1396.     if (!valueArray)
  1397.     { 
  1398.     return ObjFalse;
  1399.     }
  1400.     Array2CArray(value, valueArray);
  1401.  
  1402.     /*Make laxtX and lastY correspond to value*/
  1403.     lastX = cx + value[1] * rcos(2.0 * M_PI * value[0]);
  1404.     lastY = cy + value[1] * rsin(2.0 * M_PI * value[0]);
  1405.  
  1406.     if (flags & F_DOUBLECLICK)
  1407.     {
  1408.     /*Snap current value to closest pure hue*/
  1409.     if (value[1] < 0.33)
  1410.     {
  1411.         /*White*/
  1412.         value[1] = 0.0;
  1413.     }
  1414.     else
  1415.     {
  1416.         int testo;
  1417.         /*50 % or 100% saturated something*/
  1418.         if (value[1] > 0.66)
  1419.         {
  1420.             value[1] = 1.0;
  1421.         }
  1422.         else
  1423.         {
  1424.         value[1] = 0.5;
  1425.         }
  1426.         testo = value[0] * 6.0 + 0.5;
  1427.         value[0] = ((real) testo) / 6.0;
  1428.     }
  1429.     valueArray = NewRealArray(1, 2L);
  1430.     CArray2Array(valueArray, value);
  1431.     SetVar(object, VALUE, valueArray);
  1432.     DrawMe(object);
  1433.     ChangedValue(object);
  1434.     if (logging)
  1435.     {
  1436.         LogControl(object);
  1437.     }
  1438.     return ObjTrue;
  1439.     }
  1440.  
  1441.     dontTrack = GetPredicate(object, TRACKNOT);
  1442.  
  1443.     InhibitLogging(true);
  1444.     while (Mouse(&mouseX, &mouseY))
  1445.     {
  1446.     if (mouseX != lastX || mouseY != lastY)
  1447.     {
  1448.         real hue, saturation;
  1449.         /*Mouse has moved.  Update.*/
  1450.         sX = mouseX - cx;
  1451.         sY = mouseY - cy;
  1452.  
  1453.         if (sX == 0 && sY == 0)
  1454.         {
  1455.         /*It's at the origin, so choose 0 for h and s*/
  1456.         hue = 0.0;
  1457.         saturation = 0.0;
  1458.         }
  1459.         else
  1460.         {
  1461.         /*Hue is angle*/
  1462.         hue = atan2(((double) sY) / ((double) radius),
  1463.                 ((double) sX) / ((double) radius)) / (2.0 * M_PI);
  1464.         while (hue < 0.0) hue += 1.0;
  1465.  
  1466.         /*Saturation is radius, clipped*/
  1467.         saturation = sqrt(((double) sY) * ((double) sY) +
  1468.                   ((double) sX) * ((double) sX)) / ((double) radius);
  1469.         if (saturation > 1.0) saturation = 1.0;
  1470.         if (flags & F_SHIFTDOWN)
  1471.         {
  1472.             if (saturation > 0.66)
  1473.             {
  1474.                 saturation = 1.0;
  1475.             }
  1476.             else if (saturation > 0.33)
  1477.             {
  1478.             saturation = 0.5;
  1479.             }
  1480.             else
  1481.             {
  1482.             saturation = 0.0;
  1483.             }
  1484.         }
  1485.         }
  1486.  
  1487.         /*See if value is different*/
  1488.         valueArray = GetVar(object, VALUE);
  1489.         if (valueArray)
  1490.         {
  1491.         Array2CArray(value, valueArray);
  1492.         if (hue == value[0] && saturation == value[1])
  1493.         {
  1494.             continue;
  1495.         }
  1496.         }
  1497.         value[0] = hue;
  1498.         value[1] = saturation;
  1499.         valueArray = NewRealArray(1, 2L);
  1500.         CArray2Array(valueArray, value);
  1501.         SetVar(object, VALUE, valueArray);
  1502.         DrawMe(object);
  1503.         if (!dontTrack)
  1504.         {
  1505.         ChangedValue(object);
  1506.         }
  1507.     }
  1508.     }
  1509.     if (dontTrack)
  1510.     {
  1511.     ChangedValue(object);
  1512.     }
  1513.     InhibitLogging(false);
  1514.     if (logging)
  1515.     {
  1516.     LogControl(object);
  1517.     }
  1518.     return ObjTrue;
  1519. }
  1520.  
  1521. ObjPtr SetColorWheelVal(object, value)
  1522. ObjPtr object;
  1523. ObjPtr value;
  1524. /*Sets the value of the object to value*/
  1525. {
  1526.     if (value == NULLOBJ ||
  1527.     (IsRealArray(value) && RANK(value) == 1 && DIMS(value)[0] == 2))
  1528.     {
  1529.     SetVar(object, VALUE, value);
  1530.     ImInvalid(object);
  1531.     ChangedValue(object);
  1532.     if (logging)
  1533.     {
  1534.         LogControl(object);
  1535.     }
  1536.     return ObjTrue;
  1537.     }
  1538.     else 
  1539.     {
  1540.     return ObjFalse;
  1541.     }
  1542. }
  1543.  
  1544. static ObjPtr CleanupPalette(palette)
  1545. ObjPtr palette;
  1546. /*Cleans up the palette before deleting*/
  1547. {
  1548.     PPtr *runner;
  1549.     ObjPtr var;
  1550.     int nColors;
  1551.  
  1552.     var = GetIntVar("CleanupPalette", palette, NCOLORS);
  1553.     if (!var) return;
  1554.     nColors = GetInt(var);
  1555.  
  1556.     if ((var = GetVar(palette, BEGCOLOR)) && nColors > 0)
  1557.     {
  1558.     /*There are some colors*/
  1559.     FreeColors(GetInt(var), nColors);
  1560.     }
  1561.     runner = &activePalettes;
  1562.     while (*runner)
  1563.     {
  1564.     if (*runner == (PPtr) palette)
  1565.     {
  1566.         *runner = (*runner) -> next;
  1567.     }
  1568.     else
  1569.     {
  1570.         runner = &((*runner) -> next);
  1571.     }
  1572.     }
  1573.     return ObjTrue;
  1574. }
  1575.  
  1576. #ifdef PROTO
  1577. ObjPtr NewPalette(int nColors)
  1578. #else
  1579. ObjPtr NewPalette(nColors)
  1580. int nColors;
  1581. #endif
  1582. /*Returns a new palette of nColors, initially set to a grey ramp.  Returns
  1583.   0 if it can't.*/
  1584. {
  1585.     int k, colorBeg;
  1586.     ObjPtr retVal;
  1587.     short3 *colors, *components;
  1588.     ObjPtr var;
  1589.     long dims[2];
  1590.  
  1591.     retVal = NewObject(paletteClass, 
  1592.          sizeof(Palette) - sizeof(Thing));
  1593.     if (!retVal)
  1594.     {
  1595.     return retVal;
  1596.     }
  1597.  
  1598.     dims[0] = nColors;
  1599.     dims[1] = 3;
  1600.     var = NewArray(AT_SHORT, 2, dims);
  1601.     SetVar(retVal, COLORCOMP, var);
  1602.     if (!var)
  1603.     {
  1604.     OMErr();
  1605.     return NULLOBJ;
  1606.     }
  1607.     components = ELEMENTS(var);
  1608.  
  1609.     var = NewArray(AT_SHORT, 2, dims);
  1610.     SetVar(retVal, COLORS, var);
  1611.     if (!var)
  1612.     {
  1613.     OMErr();
  1614.     return NULLOBJ;
  1615.     }
  1616.     colors = ELEMENTS(var);
  1617.  
  1618.     ((PPtr) retVal) -> next = activePalettes;
  1619.     activePalettes = ((PPtr) retVal) -> next;
  1620.     SETOBJTYPE(retVal -> flags, PALETTE);
  1621.     SetVar(retVal, BEGCOLOR, NULLOBJ);
  1622.     SetVar(retVal, NCOLORS, NewInt(nColors));
  1623.  
  1624.     for (k = 0; k < nColors; ++k)
  1625.     {
  1626.     colors[k][0] = 
  1627.     colors[k][1] = 
  1628.     colors[k][2] = (k + 1) * 255 / nColors;
  1629.     }
  1630.     CopyColorsToComponents(retVal);
  1631.     return retVal;
  1632. }
  1633.  
  1634. #ifdef PROTO
  1635. ObjPtr NewAtomicPalette(void)
  1636. #else
  1637. ObjPtr NewAtomicPalette()
  1638. #endif
  1639. /*Returns a new atomic palette, which maps atomic numbers onto colors*/
  1640. {
  1641.     int atom;
  1642.     short3 *colors;
  1643.     ObjPtr atomNames;
  1644.     ObjPtr *namesPtr;
  1645.     ObjPtr retVal;
  1646.     ObjPtr var;
  1647.     long dim;
  1648.  
  1649.     dim = N_ATOMS + 3;
  1650.     retVal = NewPalette(dim);
  1651.     SetPaletteMinMax(retVal, 1, (real) N_ATOMS);
  1652.  
  1653.     /*Give it some colors*/
  1654.     MakeVar(retVal, COLORS);
  1655.     var = GetVar(retVal, COLORS);
  1656.     if (!var)
  1657.     {
  1658.     return NULLOBJ;
  1659.     }
  1660.     colors = ELEMENTS(var);
  1661.     colors += 2;
  1662.  
  1663.     /*Make the atom names*/
  1664.     atomNames = NewArray(AT_OBJECT, 1, &dim);
  1665.     namesPtr = ELEMENTS(atomNames);
  1666.  
  1667.     namesPtr[0] = NewString("Missing");
  1668.     namesPtr[1] = NewString("Bonds");
  1669.  
  1670.     for (atom = 0; atom < N_ATOMS; ++atom)
  1671.     {
  1672.     namesPtr[atom + 2] = NewString(atomInfo[atom] . longName);
  1673.     GetString(namesPtr[atom + 2])[0] =
  1674.         toupper(GetString(namesPtr[atom + 2])[0]);
  1675.     (*colors)[0] = atomInfo[atom] . color[0];
  1676.     (*colors)[1] = atomInfo[atom] . color[1];
  1677.     (*colors)[2] = atomInfo[atom] . color[2];
  1678.     ++colors;
  1679.     }
  1680.  
  1681.     SetVar(retVal, COLORNAMES, atomNames);
  1682.  
  1683.     return retVal;
  1684. }
  1685.  
  1686. #ifdef PROTO
  1687. void CopyPalette(ObjPtr d, ObjPtr s)
  1688. #else
  1689. void CopyPalette(d, s)
  1690. ObjPtr d, s;
  1691. #endif
  1692. /*Copies palette s to d*/
  1693. {
  1694.     int k;
  1695.     ObjPtr var;
  1696.     int nDColors, nSColors;
  1697.     short3 *dColors, *sColors;
  1698.     short3 *sComponents, *dComponents;
  1699.     long dims[2];
  1700.  
  1701.     var = GetIntVar("CopyPalette", d, NCOLORS);
  1702.     if (!var) return;
  1703.     nDColors = GetInt(var);
  1704.  
  1705.     var = GetIntVar("CopyPalette", s, NCOLORS);
  1706.     if (!var) return;
  1707.     nSColors = GetInt(var);
  1708.  
  1709.     /*Free the colors*/
  1710.     if (var = GetVar(d, BEGCOLOR))
  1711.     {
  1712.     FreeColors(GetInt(var), nDColors);
  1713.     SetVar(d, BEGCOLOR, NULLOBJ);
  1714.     }
  1715.  
  1716.     SetVar(d, CHANGED, ObjTrue);
  1717.     dims[0] = nSColors;
  1718.     dims[1] = 3;
  1719.     var = NewArray(AT_SHORT, 2, dims);
  1720.     dColors = ELEMENTS(var);
  1721.     SetVar(d, COLORS, var);
  1722.     
  1723.     var = NewArray(AT_SHORT, 2, dims);
  1724.     SetVar(d, COLORCOMP, var);
  1725.     dComponents = ELEMENTS(var);
  1726.  
  1727.     var = GetVar(s, COLORCOMP);
  1728.     sComponents = ELEMENTS(var);
  1729.  
  1730.     if (nDColors != nSColors)
  1731.     {
  1732.     SetVar(d, NCOLORS, NewInt(nSColors));
  1733.     SetVar(d, CHANGED, ObjTrue);
  1734.     }
  1735.     else
  1736.     {
  1737.     SetVar(d, JUSTCOLORCHANGE, ObjTrue);
  1738.     }
  1739.  
  1740.     SetVar(d, MINMAX, GetVar(s, MINMAX));
  1741.  
  1742.     MakeVar(s, COLORS);
  1743.     var = GetVar(s, COLORS);
  1744.     if (!var) return;
  1745.     sColors = ELEMENTS(var);
  1746.  
  1747.     for (k = 0; k < nSColors; ++k)
  1748.     {
  1749.     dColors[k][0] = sColors[k][0];
  1750.     dColors[k][1] = sColors[k][1];
  1751.     dColors[k][2] = sColors[k][2];
  1752.  
  1753.     dComponents[k][0] = sComponents[k][0];
  1754.     dComponents[k][1] = sComponents[k][1];
  1755.     dComponents[k][2] = sComponents[k][2];
  1756.     }
  1757.     SetVar(d, COLORMODEL, GetVar(s, COLORMODEL));
  1758.  
  1759.     MapPalette(d);
  1760. }
  1761.  
  1762. #ifdef PROTO
  1763. void SetPaletteNColors(ObjPtr p, int nColors)
  1764. #else
  1765. void SetPaletteNColors(p, nColors)
  1766. ObjPtr p;
  1767. int nColors;
  1768. #endif
  1769. /*Sets palette to be a nColors palette, doing any necessary resampling.*/
  1770. {
  1771.     short3 *oldColors, *colors;
  1772.     short3 *oldComponents, *components;
  1773.     real beg, end, increment;
  1774.     int s1, s2, i, k, comp;
  1775.     int temp;
  1776.     ObjPtr var;
  1777.     int oldNColors;
  1778.     long dims[2];
  1779.  
  1780.     /*Make a new set of colors*/
  1781.     /*DO NOT Make(p, COLORS)!*/
  1782.     var = GetVar(p, COLORS);
  1783.     if (!var) return;
  1784.     oldColors = ELEMENTS(var);
  1785.     oldNColors = DIMS(var)[0];
  1786.  
  1787.     dims[0] = nColors;
  1788.     dims[1] = 3;
  1789.     var = NewArray(AT_SHORT, 2, dims);
  1790.     SetVar(p, COLORS, var);
  1791.     colors = ELEMENTS(var);
  1792.  
  1793.     /*Free the colors*/
  1794.     if (var = GetVar(p, BEGCOLOR))
  1795.     {
  1796.     FreeColors(GetInt(var), oldNColors);
  1797.     SetVar(p, BEGCOLOR, NULLOBJ);
  1798.     }
  1799.  
  1800.     /*And a new set of components*/
  1801.     var = GetVar(p, COLORCOMP);
  1802.     if (!var) return;
  1803.     oldComponents = ELEMENTS(var);
  1804.     var = NewArray(AT_SHORT, 2, dims);
  1805.     SetVar(p, COLORCOMP, var);
  1806.     components = ELEMENTS(var);
  1807.  
  1808.     /*Copy ov, und, missing*/
  1809.     colors[0][0] = oldColors[0][0];
  1810.     colors[0][1] = oldColors[0][1];
  1811.     colors[0][2] = oldColors[0][2];
  1812.  
  1813.     colors[1][0] = oldColors[1][0];
  1814.     colors[1][1] = oldColors[1][1];
  1815.     colors[1][2] = oldColors[1][2];
  1816.  
  1817.     colors[nColors - 1][0] = oldColors[oldNColors - 1][0];
  1818.     colors[nColors - 1][1] = oldColors[oldNColors - 1][1];
  1819.     colors[nColors - 1][2] = oldColors[oldNColors - 1][2];
  1820.  
  1821.     increment = ((real) oldNColors - 3) / ((real) nColors - 3);
  1822.     
  1823.     for (k = 0; k < nColors - 2; ++k)
  1824.     {
  1825.     beg = k * increment;
  1826.     end = beg + increment;
  1827.     for (comp = 0; comp < 3; ++comp)
  1828.     {
  1829.         s1 = beg;
  1830.         s2 = end;
  1831.  
  1832.         if (s1 == s2)
  1833.         {
  1834.         /*Chunk of just one color*/
  1835.         colors[k + 2][comp] = oldColors[s1 + 2][comp];
  1836.         }
  1837.         else
  1838.         {
  1839.         /*Chunk of more than one color*/
  1840.         real cum;
  1841.  
  1842.         /*First one*/
  1843.         cum = (1.0 - (beg - s1)) * oldColors[s1 + 2][comp];
  1844.  
  1845.         /*Intermediate ones*/
  1846.         for (i = s1 + 3; i < s2 + 2; ++i)
  1847.         {
  1848.             cum += oldColors[i][comp];
  1849.         }
  1850.  
  1851.         /*Last one*/
  1852.         cum += (end - s2) * oldColors[s2 + 2][comp];
  1853.  
  1854.         cum /= (end - beg);
  1855.  
  1856.         temp = cum + 0.5;
  1857.         if (temp < 0) temp = 0;
  1858.         else if (temp > 255) temp = 255;
  1859.  
  1860.         colors[k + 2][comp] = temp;
  1861.         }
  1862.     }
  1863.     }
  1864.  
  1865.     /*Update nColors*/
  1866.     SetVar(p, NCOLORS, NewInt(nColors));
  1867.     CopyColorsToComponents(p);
  1868.  
  1869.     SetVar(p, CHANGED, ObjTrue);
  1870. }
  1871.  
  1872. #ifdef PROTO
  1873. void CopyAttenuatedPalette(ObjPtr d, ObjPtr s, real atten)
  1874. #else
  1875. void CopyAttenuatedPalette(d, s, atten)
  1876. ObjPtr d, s;
  1877. real atten;
  1878. #endif
  1879. /*Copies palette s to d, attenuated by d*/
  1880. {
  1881.     int k;
  1882.     ObjPtr var;
  1883.     int nDColors, nSColors;
  1884.     long dims[2];
  1885.     short3 *sColors, *dColors;
  1886.  
  1887.     var = GetIntVar("CopyAttenuatedPalette", d, NCOLORS);
  1888.     if (!var) return;
  1889.     nDColors = GetInt(var);
  1890.  
  1891.     var = GetIntVar("CopyAttenuatedPalette", s, NCOLORS);
  1892.     if (!var) return;
  1893.     nSColors = GetInt(var);
  1894.  
  1895.     /*Free the colors*/
  1896.     if (var = GetVar(d, BEGCOLOR))
  1897.     {
  1898.     FreeColors(GetInt(var), nDColors);
  1899.     SetVar(d, BEGCOLOR, NULLOBJ);
  1900.     }
  1901.  
  1902.     dims[0] = nSColors;
  1903.     dims[1] = 3;
  1904.     var = NewArray(AT_SHORT, 2, dims);
  1905.     dColors = ELEMENTS(var);
  1906.     SetVar(d, COLORS, var);
  1907.  
  1908.     var = NewArray(AT_SHORT, 2, dims);
  1909.     SetVar(d, COLORCOMP, var);
  1910.  
  1911.     MakeVar(s, COLORS);
  1912.     var = GetVar(s, COLORS);
  1913.     if (!var) return;
  1914.     sColors = ELEMENTS(var);
  1915.  
  1916.     SetVar(d, NCOLORS, NewInt(nSColors));
  1917.  
  1918.     if (nDColors != nSColors)
  1919.     {
  1920.     SetVar(d, CHANGED, ObjTrue);
  1921.     }
  1922.     else
  1923.     {
  1924.     SetVar(d, JUSTCOLORCHANGE, ObjTrue);
  1925.     }
  1926.  
  1927.     SetVar(d, MINMAX, GetVar(s, MINMAX));
  1928.  
  1929.     for (k = 0; k < nSColors; ++k)
  1930.     {
  1931.     dColors[k][0] = sColors[k][0] * atten;
  1932.     dColors[k][1] = sColors[k][1] * atten;
  1933.     dColors[k][2] = sColors[k][2] * atten;
  1934.     }
  1935.  
  1936.     CopyColorsToComponents(d);
  1937.     MapPalette(d);
  1938. }
  1939.  
  1940. ObjPtr ClonePalette(oldPalette)
  1941. ObjPtr oldPalette;
  1942. /*Clones a new palette*/
  1943. {
  1944.     ObjPtr retVal;
  1945.     short3 *colors, *components;
  1946.     ObjPtr var;
  1947.     int nColors;
  1948.     long dims[2];
  1949.  
  1950.     var = GetIntVar("ClonePalette", oldPalette, NCOLORS);
  1951.     if (!var) return;
  1952.     nColors = GetInt(var);
  1953.  
  1954.     retVal = NewObject(paletteClass,
  1955.         sizeof(Palette) - sizeof(Thing));
  1956.     if (!retVal)
  1957.     {
  1958.     return retVal;
  1959.     }
  1960.     dims[0] = nColors;
  1961.     dims[1] = 3;
  1962.     var = NewArray(AT_SHORT, 2, dims);
  1963.     colors = ELEMENTS(var);
  1964.     SetVar(retVal, COLORS, var);
  1965.  
  1966.     var = NewArray(AT_SHORT, 2, dims);
  1967.     components = ELEMENTS(var);
  1968.     SetVar(retVal, COLORCOMP, var);
  1969.  
  1970.     ((PPtr) retVal) -> next = activePalettes;
  1971.     activePalettes = ((PPtr) retVal) -> next;
  1972.     SETOBJTYPE(retVal -> flags, PALETTE);
  1973.     SetVar(retVal, BEGCOLOR, NULLOBJ);
  1974.     SetVar(retVal, NCOLORS, GetVar(oldPalette, NCOLORS));
  1975.  
  1976.     CopyPalette(retVal, oldPalette);
  1977.     return retVal;
  1978. }
  1979.  
  1980. #ifdef PROTO
  1981. void InterpPalette(ObjPtr palette,
  1982.         int r1, int g1, int b1, int r2, int g2, int b2)
  1983. #else
  1984. void InterpPalette(palette, r1, g1, b1, r2, g2, b2)
  1985. ObjPtr palette;
  1986. int r1, g1, b1, r2, g2, b2;
  1987. #endif
  1988. /*Makes palette be an interpolation between r1, g1, b1, and r2, g2, b2*/
  1989. {
  1990.     int k;
  1991.     int n;
  1992.     int nColors;
  1993.     ObjPtr var;
  1994.     long dims[2];
  1995.     short3 *colors, *oldColors;
  1996.  
  1997.     var = GetIntVar("InterpPalette", palette, NCOLORS);
  1998.     if (!var) return;
  1999.     nColors = GetInt(var);
  2000.  
  2001.     MakeVar(palette, COLORS);
  2002.     var = GetVar(palette, COLORS);
  2003.     if (!var) return;
  2004.     oldColors = ELEMENTS(var);
  2005.     dims[0] = nColors;
  2006.     dims[1] = 3;
  2007.     var = NewArray(AT_SHORT, 2, dims);
  2008.     colors = ELEMENTS(var);
  2009.     SetVar(palette, COLORS, var);
  2010.  
  2011.     n = nColors - 3;    /*Room for min, max, missing*/
  2012.  
  2013.     for (k = 0; k < n; ++k)
  2014.     {
  2015.     colors[k + 2][0] =
  2016.         (k + 1) * r2 / n + 
  2017.         (n - k) * r1 / n;
  2018.     colors[k + 2][1] = 
  2019.         (k + 1) * g2 / n + 
  2020.         (n - k) * g1 / n;
  2021.     colors[k + 2][2] =
  2022.         (k + 1) * b2 / n + 
  2023.         (n - k) * b1 / n;
  2024.     }
  2025.  
  2026.     /*Fill in missing*/
  2027.     colors[0][0] = 64;
  2028.     colors[0][1] = 64;
  2029.     colors[0][2] = 64;
  2030.  
  2031.     /*Fill in min*/
  2032.     colors[1][0] = colors[2][0];
  2033.     colors[1][1] = colors[2][1];
  2034.     colors[1][2] = colors[2][2];
  2035.  
  2036.     /*Fill in max*/
  2037.     colors[n + 2][0] = colors[n + 1][0];
  2038.     colors[n + 2][1] = colors[n + 1][1];
  2039.     colors[n + 2][2] = colors[n + 1][2];
  2040.  
  2041.     CopyColorsToComponents(palette);
  2042.  
  2043.     MapPalette(palette);
  2044. }
  2045.  
  2046. #ifdef PROTO
  2047. void BlueToRedPalette(ObjPtr p)
  2048. #else
  2049. void BlueToRedPalette(p)
  2050. ObjPtr p;
  2051. #endif
  2052. /*Makes a blue to red palette in p*/
  2053. {
  2054.     int k;
  2055.     real hue, r, g, b;
  2056.     int n;
  2057.     int nColors;
  2058.     ObjPtr var;
  2059.     short3 *colors;
  2060.     long dims[2];
  2061.  
  2062.     var = GetIntVar("BlueToRedPalette", p, NCOLORS);
  2063.     if (!var) return;
  2064.     nColors = GetInt(var);
  2065.  
  2066.     dims[0] = nColors;
  2067.     dims[1] = 3;
  2068.     var = NewArray(AT_SHORT, 2, dims);
  2069.     colors = ELEMENTS(var);
  2070.     SetVar(p, COLORS, var);
  2071.  
  2072.     n = nColors - 3;    /*Room for min, max, missing*/
  2073.  
  2074.     for (k = 0; k < n; ++k)
  2075.     {
  2076.     real v = 1.0;
  2077.     hue = (((real)(n - k))
  2078.         / (real) n) * 0.9 - 0.1;
  2079.     if (hue < 0.0) {v = 1.0 + (hue * 3.0); hue = 0.0;} 
  2080.     HSV2RGB(&r, &g, &b, hue, 1.0, v);
  2081.     colors[k + 2][0] = r * 255;
  2082.     colors[k + 2][1] = g * 255;
  2083.     colors[k + 2][2] = b * 255;
  2084.     }
  2085.  
  2086.     /*Fill in missing*/
  2087.     colors[0][0] = 64;
  2088.     colors[0][1] = 64;
  2089.     colors[0][2] = 64;
  2090.  
  2091.     /*Fill in min*/
  2092.     colors[1][0] = colors[2][0];
  2093.     colors[1][1] = colors[2][1];
  2094.     colors[1][2] = colors[2][2];
  2095.  
  2096.     /*Fill in max*/
  2097.     colors[n + 2][0] = colors[n + 1][0];
  2098.     colors[n + 2][1] = colors[n + 1][1];
  2099.     colors[n + 2][2] = colors[n + 1][2];
  2100.  
  2101.     CopyColorsToComponents(p);
  2102.  
  2103.     MapPalette(p);
  2104. }
  2105.  
  2106. #ifdef PROTO
  2107. real PSColor(void)
  2108. #else
  2109. real PSColor()
  2110. #endif
  2111. /*Returns a grayscale equivalent for the current color in DRAW_POSTSCRIPT mode*/
  2112. {
  2113.     real y, dummy;
  2114.     real h, s, v, w;
  2115.     int ival;
  2116.     real retVal;
  2117.  
  2118.     RGB2HSV(&h, &s, &v, curRed/255.0, curGreen/255.0, curBlue/255.0);
  2119.     RGB2YIQ(&y, &dummy, &dummy, curRed/255.0, curGreen/255.0, curBlue/255.0);
  2120.  
  2121.     w = (s - 0.25) * 4.0 / 3.0;
  2122.     retVal = (w * y + (1.0 - w) * v);
  2123.     if (retVal > 1.0) retVal = 1.0;
  2124.     if (retVal < 0.0) retVal = 0.0;
  2125.  
  2126.     ival = retVal * 255.0;
  2127.     retVal = ((real) LinToGamma[ival]) / 255.0;
  2128.  
  2129.     if (retVal > 1.0) retVal = 1.0;
  2130.     if (retVal < 0.0) retVal = 0.0;
  2131.     return retVal;
  2132. }
  2133.  
  2134. #ifdef PROTO
  2135. void SetUIColor(int c)
  2136. #else
  2137. void SetUIColor(c)
  2138. int c;
  2139. #endif
  2140. /*Sets the current drawing color to user interface color c, regardless
  2141.   of whether the current window is RGB or colormap*/
  2142. {
  2143. #ifdef GRAPHICS
  2144.     if (drawingMode == DRAW_SCREEN)
  2145.     {
  2146.     if (overDraw)
  2147.     {
  2148.         if (overDrawMenus)
  2149.         {
  2150.         color(c);
  2151.         }
  2152.         else
  2153.         {
  2154.         if (c == UIBLACK)
  2155.         {
  2156.             color(UIOVERCLEAR);
  2157.         }
  2158.         else
  2159.         {
  2160.             color(UIOVERRED);
  2161.         }
  2162.         }
  2163.     }
  2164.     else
  2165.     if (rgbp)
  2166.     {
  2167.         /*It's an RGB window*/
  2168.         lmcolor(LMC_COLOR);
  2169.         c3s(uiColors[c]);
  2170.     }
  2171.     else
  2172.     {
  2173.         /*It's a cmap window*/
  2174.         color(uiColorIndex[c]);
  2175.     }
  2176.     }
  2177.     else
  2178.     {
  2179.     curRed = uiColors[c][0];
  2180.     curGreen = uiColors[c][1];
  2181.     curBlue = uiColors[c][2];
  2182.     }
  2183. #endif
  2184. }
  2185.  
  2186. #ifdef PROTO
  2187. ObjPtr NewColorWheel(int left, int right, int bottom, int top, char *name)
  2188. #else
  2189. ObjPtr NewColorWheel(left, right, bottom, top, name)
  2190. int left, right, bottom, top;
  2191. char *name;
  2192. #endif
  2193. /*Makes a new hue/saturation control in left, right, bottom, top*/
  2194. {
  2195.     real value[2];
  2196.     ObjPtr valueArray;
  2197.     ObjPtr retVal;
  2198.  
  2199.     
  2200.     value[0] = 0.0;
  2201.     value[1] = 0.0;
  2202.     valueArray = NewRealArray(1, (long) 2);
  2203.     if (valueArray)
  2204.     {
  2205.     CArray2Array(valueArray, value);
  2206.  
  2207.     retVal = NewObject(colorWheelClass, 0);
  2208.     Set2DIntBounds(retVal, left, right, bottom, top);
  2209.     SetVar(retVal, VALUE, valueArray);
  2210.     SetVar(retVal, NAME, NewString(name));
  2211.     return retVal;
  2212.     }
  2213.     else
  2214.     {
  2215.     return NULLOBJ;
  2216.     }
  2217. }
  2218.  
  2219. #ifdef PROTO
  2220. static int ColorToPixel(ObjPtr colorBar, int clr)
  2221. #else
  2222. static int ColorToPixel(colorBar, clr)
  2223. ObjPtr colorBar;
  2224. int clr;
  2225. #endif
  2226. /*Returns the horizontal pixel for the color value in clr*/
  2227. {
  2228.     int left, right, bottom, top;
  2229.     ObjPtr palette;
  2230.     int nColors;
  2231.     ObjPtr var;
  2232.  
  2233.     /*Get the palette*/
  2234.     palette = GetPaletteVar("ColorToPixel", colorBar, REPOBJ);
  2235.     if (!palette)
  2236.     {
  2237.     return 0;
  2238.     }
  2239.  
  2240.     Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
  2241.  
  2242.     /*Get the stuff from the palette*/
  2243.  
  2244.     var = GetIntVar("ColorToPixel", palette, NCOLORS);
  2245.     if (!var) return;
  2246.     nColors = GetInt(var);
  2247.  
  2248.     if (clr == 0)
  2249.     {
  2250.     /*Missing*/
  2251.     return left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2;
  2252.     }
  2253.     else if (clr == 1)
  2254.     {
  2255.     /*Underflow*/
  2256.     return left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2;
  2257.     }
  2258.     else if (clr == nColors - 1)
  2259.     {
  2260.     /*Overflow*/
  2261.     return right - CBRBORDER - CBBOXWIDTH / 2;
  2262.     }
  2263.     else
  2264.     {
  2265.     /*In the center*/
  2266.     int r, l;
  2267.  
  2268.     l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  2269.     r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  2270.  
  2271.     return ((clr - 2) * (r - l) + (r - l) / 2) / (nColors - 3) + l;
  2272.     }
  2273. }
  2274.  
  2275. #ifdef PROTO
  2276. static Bool ColorToPixels(int *lPix, int *rPix, ObjPtr colorBar, int clr)
  2277. #else
  2278. static Bool ColorToPixels(lPix, rPix, colorBar, clr)
  2279. ObjPtr colorBar;
  2280. int clr;
  2281. int *lPix, *rPix;
  2282. #endif
  2283. /*Returns the horizontal pixelx around the color value in clr*/
  2284. {
  2285.     int left, right, bottom, top;
  2286.     ObjPtr palette;
  2287.     int nColors;
  2288.     ObjPtr var;
  2289.  
  2290.     /*Get the palette*/
  2291.     palette = GetPaletteVar("ColorToPixel", colorBar, REPOBJ);
  2292.     if (!palette)
  2293.     {
  2294.     return false;
  2295.     }
  2296.  
  2297.     Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
  2298.  
  2299.     /*Get the stuff from the palette*/
  2300.     var = GetIntVar("ColorToPalette", palette, NCOLORS);
  2301.     if (!var) return;
  2302.     nColors = GetInt(var);
  2303.  
  2304.     if (clr == 0)
  2305.     {
  2306.     /*Missing*/
  2307.     *lPix = left + CBLBORDER + CBLTEXTSPACE + 1;
  2308.     *rPix = left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1;
  2309.     return true;
  2310.     }
  2311.     else if (clr == 1)
  2312.     {
  2313.     /*Underflow*/
  2314.     *lPix = left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1;
  2315.     *rPix = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1;
  2316.     return true;
  2317.     }
  2318.     else if (clr == nColors - 1)
  2319.     {
  2320.     /*Overflow*/
  2321.     *lPix = right - CBRBORDER - CBBOXWIDTH + 1;
  2322.     *rPix = right - CBRBORDER - 1;
  2323.     return true;
  2324.     }
  2325.     else
  2326.     {
  2327.     /*In the center*/
  2328.     int r, l;
  2329.  
  2330.     l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  2331.     r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  2332.  
  2333.     if (clr == 2)
  2334.     {
  2335.         *lPix = l;
  2336.     }
  2337.     else
  2338.     {
  2339.         *lPix = l + (clr - 2) * (r - l) / (nColors - 3) + 1;
  2340.     }
  2341.     *rPix = l + (clr - 1) * (r - l) / (nColors - 3);
  2342.  
  2343.     return true;
  2344.     }
  2345. }
  2346.  
  2347. #ifdef PROTO
  2348. static int PixelToColor(ObjPtr colorBar, int pix)
  2349. #else
  2350. static int PixelToColor(colorBar, pix)
  2351. ObjPtr colorBar;
  2352. int pix;
  2353. #endif
  2354. /*Returns the color for the horizontal pixel pixel*/
  2355. {
  2356.     int left, right, bottom, top;
  2357.     ObjPtr palette;
  2358.     int nColors;
  2359.     ObjPtr var;
  2360.  
  2361.     /*Get the palette*/
  2362.     palette = GetPaletteVar("ColorToPixel", colorBar, REPOBJ);
  2363.     if (!palette)
  2364.     {
  2365.     return 0;
  2366.     }
  2367.  
  2368.     Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
  2369.  
  2370.     /*Get the stuff from the palette*/
  2371.     var = GetIntVar("ColorToPalette", palette, NCOLORS);
  2372.     if (!var) return;
  2373.     nColors = GetInt(var);
  2374.  
  2375.     if (pix < left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP / 2)
  2376.     {
  2377.     /*Missing*/
  2378.     return 0;
  2379.     }
  2380.     else if (pix < left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP)
  2381.     {
  2382.     /*Underflow*/
  2383.     return 1;
  2384.     }
  2385.     else if (pix > right - CBRBORDER - CBBOXWIDTH)
  2386.     {
  2387.     /*Overflow*/
  2388.     return nColors - 1;
  2389.     }
  2390.     else
  2391.     {
  2392.     /*In the center*/
  2393.     int r, l, retVal;
  2394.  
  2395.     l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  2396.     r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  2397.     retVal = ((pix - l) * (nColors - 3) + (nColors - 3) / 2) / (r - l)
  2398.         + 2;
  2399.     if (retVal >= nColors - 1)
  2400.     {
  2401.         retVal = nColors - 2;
  2402.     }
  2403.     if (retVal < 2)
  2404.     {
  2405.         retVal = 2;
  2406.     }
  2407.     return retVal;
  2408.     }
  2409. }
  2410.  
  2411. #ifdef PROTO
  2412. void CalcGoodSteps(double diff, int pixWidth, int minMajorPix, double *majorWidth, int *nMinorSteps)
  2413. #else
  2414. void CalcGoodSteps(diff, pixWidth, minMajorPix, majorWidth, nMinorSteps)
  2415. double diff;
  2416. int pixWidth;
  2417. int minMajorPix;
  2418. double *majorWidth;
  2419. int *nMinorSteps;
  2420. #endif
  2421. /*Calculates good steps for a 10-base scale
  2422.   diff is the difference between minimum and max
  2423.   pixWidth is the width in pixels between minimum and max
  2424.   minMajorPix is the minimum number of pixels between major tics
  2425.   *majorWidth will be the width of a major step
  2426.   *nMinorTics will be the number of minor steps
  2427. */
  2428. {
  2429.     double deltaLog;    /*Log of the delta at minimum*/
  2430.     double minDelta;    /*Minimum delta between major tics*/
  2431.     double pixPerMajor;    /*Pixels per major step*/
  2432.     double l, m, n;
  2433.  
  2434.     if (diff < 0.0)
  2435.     {
  2436.     diff = -diff;
  2437.     }
  2438.  
  2439.     if (diff <= 0.0)
  2440.     {
  2441.     /*Set it to something so that it doesn't blow up*/
  2442.     *majorWidth = 1.0;
  2443.     *nMinorSteps = 10;
  2444.     return;
  2445.     }
  2446.  
  2447.     minDelta = diff * minMajorPix / pixWidth;
  2448.  
  2449.     l = log(minDelta) / LOGE10;
  2450.     m = log10(minDelta);
  2451.     n = log(minDelta);
  2452.  
  2453. #ifdef DEBUG
  2454.     printf("log(x) / log(10) = %lg\n", l);
  2455.     printf("log10(x) = %lg\n", m);
  2456.     printf("log(x) = %lg\n", n);
  2457. #endif
  2458.  
  2459.     deltaLog = floor(l);
  2460.     *majorWidth = pow((double) 10.0, deltaLog);
  2461.     *nMinorSteps = 10;
  2462.  
  2463.     while (*majorWidth < minDelta)
  2464.     {
  2465.     if (*majorWidth < minDelta)
  2466.     {
  2467.         /*Try 2*/
  2468.         *majorWidth *= 2.0;
  2469.         *nMinorSteps = 2;
  2470.     }
  2471.     if (*majorWidth < minDelta)
  2472.     {
  2473.         /*Try 5*/
  2474.         *majorWidth *= 2.5;
  2475.         *nMinorSteps = 5;
  2476.     }
  2477.     if (*majorWidth < minDelta)
  2478.     {
  2479.         /*Try 10*/
  2480.         *majorWidth *= 2.0;
  2481.         *nMinorSteps = 10;
  2482.     }
  2483.     }
  2484.  
  2485.     /*Adjust to eliminate sub-3-pixel minor tics*/
  2486.     pixPerMajor = *majorWidth * pixWidth / diff;
  2487.     if (pixPerMajor / *nMinorSteps < 3 &&
  2488.        *nMinorSteps > 1)
  2489.     {
  2490.     *nMinorSteps = 1;
  2491.     }
  2492. }
  2493.  
  2494. #ifdef PROTO
  2495. void ResetColorBarTools(ObjPtr colorBar)
  2496. #else
  2497. void ResetColorBarTools(colorBar)
  2498. ObjPtr colorBar;
  2499. #endif
  2500. /*Resets the tools associated with a color bar*/
  2501. {
  2502.     ObjPtr radio, freeFormButton;
  2503.     
  2504.     InhibitLogging(true);
  2505.     freeFormButton = GetVar(colorBar, FREEFORMBUTTON);
  2506.     radio = GetVar(colorBar, TOOLGROUP);
  2507.     if (radio)
  2508.     {
  2509.     /***UPDATE For some reason, this doesn't work properly.*/
  2510.     SetValue(radio, NewInt(freeFormButton ? 
  2511.                 (GetPredicate(freeFormButton, ACTIVATED) ? PT_FREEFORM : -1)
  2512.                 : PT_FREEFORM));
  2513.     }
  2514.     InhibitLogging(false);
  2515. }
  2516.  
  2517. ObjPtr SetColorBarVal(object, value)
  2518. ObjPtr object;
  2519. ObjPtr value;
  2520. /*Sets the value of the object to value*/
  2521. {
  2522.     if (IsRealArray(value) && RANK(value) == 1 && DIMS(value)[0] == 3)
  2523.     {
  2524.     ObjPtr radio;
  2525.     ObjPtr repObj;
  2526.     real *elements;
  2527.     ObjPtr var;
  2528.     int nColors;
  2529.  
  2530.     elements = ELEMENTS(value);
  2531.     if (elements[0] < 0.0 || elements[0] > 3.0 ||
  2532.         elements[1] < 0.0 || elements[2] < 0.0)
  2533.     {
  2534.         ReportError("SetColorBarVal", "Value error");
  2535.         return ObjFalse;
  2536.     }
  2537.  
  2538.     repObj = GetPaletteVar("SetColorBarVal", object, REPOBJ);
  2539.     if (repObj)
  2540.     {
  2541.         var = GetIntVar("SetColorBarVal", repObj, NCOLORS);
  2542.         if (!var)
  2543.         {
  2544.         return ObjFalse;
  2545.         }
  2546.         nColors = GetInt(var);
  2547.         if (elements[1] >= ((real) nColors) - 0.5 ||
  2548.         elements[2] >= ((real) nColors) - 0.5)
  2549.         {
  2550.         ReportError("SetColorBarVal", "Value error");
  2551.         return ObjFalse;
  2552.         }
  2553.     }
  2554.  
  2555.     SetVar(object, VALUE, value);
  2556.     ImInvalid(object);
  2557.  
  2558.     ChangedValue(object);
  2559.     if (logging)
  2560.     {
  2561.         LogControl(object);
  2562.     }
  2563.  
  2564.     /*Set the edit tool to 0*/
  2565.     ResetColorBarTools(object);
  2566.  
  2567.     return ObjTrue;
  2568.     }
  2569.     else
  2570.     {
  2571.     ReportError("SetColorBarVal", "Bad value for color bar");
  2572.     return ObjFalse;
  2573.     }
  2574. }
  2575.  
  2576. #ifdef PROTO
  2577. static ObjPtr ReinitColorBar(ObjPtr colorBar)
  2578. #else
  2579. static ObjPtr ReinitColorBar(colorBar)
  2580. ObjPtr colorBar;
  2581. #endif
  2582. /*Reinitializes a color bar*/
  2583. {
  2584.     return ObjTrue;
  2585. }
  2586.  
  2587. #ifdef PROTO
  2588. real GetColorValue(ObjPtr palette, int color)
  2589. #else
  2590. real GetColorValue(palette, color)
  2591. ObjPtr palette;
  2592. int color;
  2593. #endif
  2594. /*Gets a field value for center of color color.  Ignores missing*/
  2595. {
  2596.     ObjPtr var;
  2597.     real *minmax;
  2598.     int nColors;
  2599.  
  2600.     var = GetFixedArrayVar("GetColorValue", palette, MINMAX, 1, 2L);
  2601.     if (!var)
  2602.     {
  2603.     return 0.0;
  2604.     }
  2605.  
  2606.     minmax = ELEMENTS(var);
  2607.     var = GetIntVar("GetColorValue", palette, NCOLORS);
  2608.     if (!var)
  2609.     {
  2610.     return 0.0;
  2611.     }
  2612.     nColors = GetInt(var);
  2613.  
  2614.     return
  2615.     minmax[0] +
  2616.     (color - 2) * (minmax[1] - minmax[0]) /
  2617.     (nColors - 4);
  2618. }
  2619.  
  2620. static int hueColors[7] =
  2621.     {
  2622.     UIRED, UIYELLOW, UIGREEN, UICYAN, UIBLUE, UIMAGENTA, UIRED
  2623.     };
  2624.  
  2625. #ifdef PROTO
  2626. static void ColorModelRect(int left, int right, int bottom, int top, int cm, int k)
  2627. #else
  2628. static void ColorModelRect(left, right, bottom, top, cm, k)
  2629. int left;
  2630. int right;
  2631. int bottom;
  2632. int top;
  2633. int cm;
  2634. int k;
  2635. #endif
  2636. /*Fills a rectangle within the bounds for color model cm in field k*/
  2637. {
  2638. #ifdef GRAPHICS
  2639.     switch (cm)
  2640.     {
  2641.     case CM_RGB:
  2642.         FillUIRect(left, right, bottom, top, 
  2643.             k == 1 ? UIBLUE : k == 2 ? UIGREEN : UIRED);
  2644.         break;
  2645.     case CM_HSV:
  2646.     case CM_HLS:
  2647.         shademodel(GOURAUD);
  2648.         if (k == 3)
  2649.         {
  2650.         /*Hue*/
  2651.         int c;
  2652.         long v[2];
  2653.  
  2654.         bgnpolygon();
  2655.         SetUIColor(UIRED);
  2656.         v[1] = bottom;
  2657.         v[0] = left;
  2658.         v2i(v);
  2659.         v[0] = right;
  2660.         v2i(v);
  2661.  
  2662.         for (c = 1; c < 5; ++c)
  2663.         {
  2664.             SetUIColor(hueColors[c]);
  2665.             v[1] = bottom + (top - bottom) * c / 6;
  2666.             v[0] = right;
  2667.             v2i(v);
  2668.             v[0] = left;
  2669.             v2i(v);
  2670.             endpolygon();
  2671.  
  2672.             bgnpolygon();
  2673.             v2i(v);
  2674.             v[0] = right;
  2675.             v2i(v);
  2676.         }
  2677.         SetUIColor(hueColors[c]);
  2678.         v[1] = top;
  2679.         v[0] = right;
  2680.         v2i(v);
  2681.         v[0] = left;
  2682.         v2i(v);
  2683.         endpolygon();
  2684.         }
  2685.         else if ((cm == CM_HSV && k == 2) ||
  2686.              (cm == CM_HLS && k == 1))
  2687.         {
  2688.         /*Saturation*/
  2689.         long v[2];
  2690.         bgnpolygon();
  2691.         SetUIColor(UIWHITE);
  2692.         v[0] = left;
  2693.         v[1] = bottom;
  2694.         v2i(v);
  2695.         v[0] = right;
  2696.         v2i(v);
  2697.         SetUIColor(UICYAN);
  2698.         v[1] = top;
  2699.         v2i(v);
  2700.         v[0] = left;
  2701.         v2i(v);
  2702.         endpolygon();
  2703.         }
  2704.         else if (cm == CM_HSV)
  2705.         {
  2706.         /*Must be value*/
  2707.         long v[2];
  2708.         bgnpolygon();
  2709.         SetUIColor(UIBLACK);
  2710.         v[0] = left;
  2711.         v[1] = bottom;
  2712.         v2i(v);
  2713.         v[0] = right;
  2714.         v2i(v);
  2715.         SetUIColor(UICYAN);
  2716.         v[1] = top;
  2717.         v2i(v);
  2718.         v[0] = left;
  2719.         v2i(v);
  2720.         endpolygon();
  2721.         }
  2722.         else
  2723.         {
  2724.         /*Must be lightness*/
  2725.         long v[2];
  2726.         bgnpolygon();
  2727.         SetUIColor(UIBLACK);
  2728.         v[0] = left;
  2729.         v[1] = bottom;
  2730.         v2i(v);
  2731.         v[0] = right;
  2732.         v2i(v);
  2733.         SetUIColor(UICYAN);
  2734.         v[1] = (top + bottom) / 2;
  2735.         v2i(v);
  2736.         v[0] = left;
  2737.         v2i(v);
  2738.         endpolygon();
  2739.  
  2740.         bgnpolygon();
  2741.         v[0] = left;
  2742.         v2i(v);
  2743.         v[0] = right;
  2744.         v2i(v);
  2745.         SetUIColor(UIWHITE);
  2746.         v[1] = top;
  2747.         v2i(v);
  2748.         v[0] = left;
  2749.         v2i(v);
  2750.         endpolygon();
  2751.         }
  2752.     
  2753.         shademodel(FLAT);
  2754.         break;
  2755.     case CM_YIQ:
  2756.         shademodel(GOURAUD);
  2757.         if (k == 3)
  2758.         {
  2759.         /*Must be y*/
  2760.         long v[2];
  2761.         bgnpolygon();
  2762.         SetUIColor(UIBLACK);
  2763.         v[0] = left;
  2764.         v[1] = bottom;
  2765.         v2i(v);
  2766.         v[0] = right;
  2767.         v2i(v);
  2768.         SetUIColor(UICYAN);
  2769.         v[1] = (top + bottom) / 2;
  2770.         v2i(v);
  2771.         v[0] = left;
  2772.         v2i(v);
  2773.         endpolygon();
  2774.  
  2775.         bgnpolygon();
  2776.         v[0] = left;
  2777.         v2i(v);
  2778.         v[0] = right;
  2779.         v2i(v);
  2780.         SetUIColor(UIWHITE);
  2781.         v[1] = top;
  2782.         v2i(v);
  2783.         v[0] = left;
  2784.         v2i(v);
  2785.         endpolygon();
  2786.         }
  2787.         else if (k == 2)
  2788.         {
  2789.         /*i, cyan/orange index (use red instead of orange)*/
  2790.         long v[2];
  2791.         bgnpolygon();
  2792.         SetUIColor(UICYAN);
  2793.         v[0] = left;
  2794.         v[1] = bottom;
  2795.         v2i(v);
  2796.         v[0] = right;
  2797.         v2i(v);
  2798.         SetUIColor(UIRED);
  2799.         v[1] = top;
  2800.         v2i(v);
  2801.         v[0] = left;
  2802.         v2i(v);
  2803.         endpolygon();
  2804.         }
  2805.         else
  2806.         {
  2807.         /*q, green/magenta axis*/
  2808.         long v[2];
  2809.         bgnpolygon();
  2810.         SetUIColor(UIGREEN);
  2811.         v[0] = left;
  2812.         v[1] = bottom;
  2813.         v2i(v);
  2814.         v[0] = right;
  2815.         v2i(v);
  2816.         SetUIColor(UIMAGENTA);
  2817.         v[1] = top;
  2818.         v2i(v);
  2819.         v[0] = left;
  2820.         v2i(v);
  2821.         endpolygon();
  2822.         }
  2823.     
  2824.         shademodel(FLAT);
  2825.         break;
  2826.     }
  2827. #endif
  2828. }
  2829.  
  2830. #ifdef PROTO
  2831. static void DrawFunctionBox(real *elements, int l, int r, int b, int t, real start, real finish)
  2832. #else
  2833. static void DrawFunctionBox(elements, l, r, b, t, start, finish)
  2834. real *elements;
  2835. int l, r, b, t;
  2836. real start, finish;
  2837. #endif
  2838. /*Draws a function box*/
  2839. {
  2840.         int boxL, boxR, boxB, boxT, boxX, boxY;
  2841.     real ddiff;
  2842.  
  2843.     ddiff = finish - start;
  2844.  
  2845.         boxL = l + (elements[0] - start) * (r - l) / (ddiff);
  2846.         boxR = l + (elements[1] - start) * (r - l) / (ddiff);
  2847.         boxB = b + elements[2] * (t - b) / 255.0;
  2848.         boxT = b + elements[3] * (t - b) / 255.0;
  2849.         boxX = (boxL + boxR) / 2;
  2850.         boxY = (boxB + boxT) / 2;
  2851.  
  2852.         /*Now draw the box and its handles*/
  2853.         FrameUIRect(boxL + 1, boxR + 2, boxB - 2, boxT - 1, UIBLACK);
  2854.         FrameUIRect(boxL + 1 - CBHANDLESIZE, boxL + 1,
  2855.                 boxY - 1 - CBHANDLESIZE / 2, boxY - 1 + CBHANDLESIZE / 2, UIBLACK);
  2856.         FrameUIRect(boxR + 2, boxR + 2 + CBHANDLESIZE,
  2857.                 boxY - 1 - CBHANDLESIZE / 2, boxY - 1 + CBHANDLESIZE / 2, UIBLACK);
  2858.         FrameUIRect(boxX + 2 - CBHANDLESIZE / 2, boxX + 2 + CBHANDLESIZE / 2,
  2859.                 boxT - 1, boxT - 1 + CBHANDLESIZE, UIBLACK);
  2860.         FrameUIRect(boxX + 2 - CBHANDLESIZE / 2, boxX + 2 + CBHANDLESIZE / 2,
  2861.                 boxB - 2 - CBHANDLESIZE, boxB - 2, UIBLACK);
  2862.  
  2863.         FrameUIRect(boxL, boxR, boxB, boxT, UIYELLOW);
  2864.         FrameUIRect(boxL - 1, boxR + 1, boxB - 1, boxT + 1, UIYELLOW);
  2865.  
  2866.         FillUIRect(boxL - 1 - CBHANDLESIZE, boxL,
  2867.                 boxY - CBHANDLESIZE / 2, boxY + 1 + CBHANDLESIZE / 2, UIYELLOW);
  2868.         FillUIRect(boxR, boxR + 1 + CBHANDLESIZE,
  2869.                 boxY - CBHANDLESIZE / 2, boxY + 1 + CBHANDLESIZE / 2, UIYELLOW);
  2870.         FillUIRect(boxX - CBHANDLESIZE / 2, boxX + 1 + CBHANDLESIZE / 2,
  2871.                 boxT, boxT + 1 + CBHANDLESIZE, UIYELLOW);
  2872.         FillUIRect(boxX - CBHANDLESIZE / 2, boxX + 1 + CBHANDLESIZE / 2,
  2873.                 boxB - 1 - CBHANDLESIZE, boxB, UIYELLOW);
  2874. }
  2875.  
  2876. static ObjPtr DrawColorBar(colorBar)
  2877. ObjPtr colorBar;
  2878. /*Draws a color bar*/
  2879. {
  2880. #ifdef GRAPHICS
  2881.     int left, right, bottom, top;
  2882.     int l, r, b, t;
  2883.     int start, diff, comp;
  2884.     ObjPtr palette;
  2885.     int nColors;
  2886.     short3 *colors;
  2887.     ObjPtr value;            /*Value of the control*/
  2888.     real *elements;
  2889.     ObjPtr var;
  2890.     int highlighted;
  2891.     int k;
  2892.     double majorWidth, minorWidth;    /*Width of a major step*/
  2893.     double ddiff;                /*Data difference*/
  2894.     int nTics;                /*Number of minor tics*/
  2895.     long temp;
  2896.     double halfSpace;
  2897.     int pixel;                /*Temporary pixel*/
  2898.     double curValue;            /*Current value for making tics*/
  2899.     int cm;                /*Color model in use*/
  2900.     real *minmax;
  2901.  
  2902.     Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
  2903.     if (IsDrawingRestricted(left, right, bottom, top)) return ObjFalse;
  2904.  
  2905.     /*Get the palette*/
  2906.     palette = GetPaletteVar("DrawColorBar", colorBar, REPOBJ);
  2907.     if (!palette)
  2908.     {
  2909.     return ObjFalse;
  2910.     }
  2911.  
  2912.     /*Get the stuff from the palette*/
  2913.     var = GetIntVar("DrawColorBar", palette, NCOLORS);
  2914.     if (!var) return;
  2915.     nColors = GetInt(var);
  2916.  
  2917.     MakeVar(palette, COLORS);
  2918.     var = GetVar(palette, COLORS);
  2919.     if (!var) return;
  2920.     colors = ELEMENTS(var);
  2921.  
  2922.     /*Draw the bump and plateau, but not if the changed bounds is smaller than
  2923.       the bounds*/
  2924.     var = GetVar(colorBar, CHANGEDBOUNDS);
  2925.     if (!var || !IsArray(var))
  2926.     {
  2927.     DrawRaisedRect(left, right, bottom, top, UIBACKGROUND);
  2928.     }
  2929.     else
  2930.     {
  2931.     elements = ELEMENTS(var);
  2932.     if (left >= CURSTATE . screenMask[0] - CURSTATE . translation[0] &&
  2933.         right <= CURSTATE . screenMask[1] - CURSTATE . translation[0]  &&
  2934.         bottom >= CURSTATE . screenMask[2] - CURSTATE . translation[1]  &&
  2935.         top <= CURSTATE . screenMask[3] - CURSTATE . translation[1])
  2936.     {
  2937.         DrawRaisedRect(left, right, bottom, top, UIBACKGROUND);
  2938.     }
  2939.     }
  2940.  
  2941.     /*Draw the legends and tic marks and stuff at the bottom*/
  2942.     SetUIColor(UIBLACK);
  2943.     SetUIFont(CBTEXTFONT);
  2944.     b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP;
  2945.  
  2946.     DrawAString(CENTERALIGN, 
  2947.         left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2,
  2948.         bottom + CBBORDER + CBTEXTUP, "Missing");
  2949.     DrawUILine( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2, b,
  2950.         left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2, b - CBMAJORTICLEN, UIBLACK);
  2951.     DrawAString(CENTERALIGN,
  2952.         left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2,
  2953.         bottom + CBBORDER + CBTEXTUP, "Under");
  2954.     DrawUILine( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2, b,
  2955.         left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2, b - CBMAJORTICLEN, UIBLACK);
  2956.  
  2957.     /*Draw all the tics in the middle*/
  2958.     l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  2959.     r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  2960.     var = GetVar(palette, MINMAX);
  2961.     if (!var)
  2962.     {
  2963.     return ObjFalse;
  2964.     }
  2965.     minmax = ELEMENTS(var);
  2966.     ddiff = minmax[1] - minmax[0];
  2967.     halfSpace = ddiff / (nColors - 4) * 0.5;
  2968.  
  2969.     CalcGoodSteps(ddiff,
  2970.           r - l,
  2971.           CBSTEPPIXELS,
  2972.           &majorWidth, &nTics);
  2973.     minorWidth = majorWidth / nTics;
  2974.  
  2975.     /*Minor and major tics first*/
  2976.     temp = minmax[0] / majorWidth;
  2977.     curValue = temp * majorWidth;
  2978.  
  2979.     while (curValue > minmax[0])
  2980.     {
  2981.     curValue -= majorWidth;
  2982.     }
  2983.     k = 0;
  2984.     while (curValue < minmax[0])
  2985.     {
  2986.     ++k;
  2987.     if (k >= nTics) k = 0;
  2988.  
  2989.     curValue += minorWidth;
  2990.     }
  2991.  
  2992.     /*Now actually draw them*/
  2993.     if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  2994.     while (curValue <= minmax[1] + ddiff * 1.0E-6)
  2995.     {
  2996.     pixel = l + (curValue - minmax[0]) * (r - l) / (ddiff);
  2997.     if (k == 0)
  2998.     {
  2999.         /*Major tic*/
  3000.         DrawUILine(pixel, b,
  3001.                pixel, b - CBMAJORTICLEN,
  3002.                UIBLACK);
  3003.         sprintf(tempStr, "%lg", curValue);
  3004.         DrawAString(CENTERALIGN, pixel, b - CBTEXTSEP, tempStr);
  3005.     }
  3006.     else
  3007.     {
  3008.         /*Minor tic*/
  3009.         DrawUILine(pixel, b,
  3010.                pixel, b - CBMAJORTICLEN / 2,
  3011.                UIBLACK);
  3012.     }
  3013.  
  3014.     curValue += minorWidth;
  3015.     if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  3016.     ++k;
  3017.     if (k >= nTics) k = 0;
  3018.     }
  3019.  
  3020.     DrawAString(CENTERALIGN,
  3021.         right - CBRBORDER - CBBOXWIDTH + CBBOXWIDTH / 2,
  3022.         bottom + CBBORDER + CBTEXTUP, "Over");
  3023.     DrawUILine( right - CBRBORDER - CBBOXWIDTH + CBBOXWIDTH / 2, b,
  3024.         right - CBRBORDER - CBBOXWIDTH + CBBOXWIDTH / 2, b - CBMAJORTICLEN, UIBLACK);
  3025.  
  3026.     /*Get the color model*/
  3027.     var = GetIntVar("DrawColorBar", palette, COLORMODEL);
  3028.     if (!var)
  3029.     {
  3030.     return ObjFalse;
  3031.     }
  3032.     cm = GetInt(var);
  3033.  
  3034.     /*Draw the boxes*/
  3035.     b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP;
  3036.     SetUIFont(CBBIGTEXTFONT);
  3037.  
  3038.     for (k = 0; k < 4; ++k)
  3039.     {
  3040.     t = b + CBCOMPHEIGHT;
  3041.  
  3042.     /*Draw the box outlines*/
  3043.  
  3044.     /*Draw the missing data box*/
  3045.     FrameUIRect(left + CBLBORDER + CBLTEXTSPACE, left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH, b, t, UIBLACK);
  3046.  
  3047.     /*Now the underflow box*/
  3048.     FrameUIRect(left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP,
  3049.         left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP,
  3050.         b, t, UIBLACK);
  3051.  
  3052.     /*Now the middle bit*/
  3053.     FrameUIRect(left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP,
  3054.         right  - CBRBORDER - CBBOXWIDTH - CBHGAP,
  3055.         b, t, UIBLACK);
  3056.  
  3057.     /*Now the overflow box*/
  3058.     FrameUIRect(right - CBRBORDER - CBBOXWIDTH,
  3059.         right - CBRBORDER,
  3060.         b, t, UIBLACK);
  3061.  
  3062.     /*Draw the background of the boxex*/
  3063.  
  3064.     /*Draw the missing data box*/
  3065.     ColorModelRect(left + CBLBORDER + CBLTEXTSPACE + 1, left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, b + 1, t - 1, 
  3066.             cm, k);
  3067.  
  3068.     /*Now the underflow box*/
  3069.     ColorModelRect(left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1,
  3070.             left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1,
  3071.             b + 1, t - 1, cm, k);
  3072.  
  3073.     /*Now the middle bit*/
  3074.     ColorModelRect(left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1,
  3075.             right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1,
  3076.             b + 1, t - 1, cm, k);
  3077.  
  3078.     /*Now the overflow box*/
  3079.     ColorModelRect(right - CBRBORDER - CBBOXWIDTH + 1,
  3080.             right - CBRBORDER - 1,
  3081.             b + 1, t - 1, cm, k);
  3082.  
  3083.     /*Now the component names*/
  3084.     if (k)
  3085.     {
  3086.         SetUIColor(UIBLACK);
  3087.         DrawAString(LEFTALIGN, 
  3088.         left + CBLBORDER, (b + t) / 2 - CBCOMPTEXTDOWN,
  3089.         shortComponentNames[cm][3 - k]);
  3090.     }
  3091.  
  3092.     b = t + CBVGAP;
  3093.     }
  3094.  
  3095.     /*Now the expanded readout*/
  3096.     FrameUIRect(left + CBLBORDER,
  3097.         right  - CBRBORDER,
  3098.         b, top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP, UIBLACK);
  3099.  
  3100.     b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP + 1;
  3101.     t = b + CBCOMPHEIGHT - 2;
  3102.  
  3103.     /*Now draw the colors*/
  3104.     if (rgbp)
  3105.     {
  3106.     /*It's in RGB mode, so we don't have to set the palette*/
  3107.  
  3108.     l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  3109.     r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  3110.  
  3111.     /*Do missing data box*/
  3112.     c3s(colors[0]);
  3113.     FillRect( left + CBLBORDER + CBLTEXTSPACE + 1, 
  3114.         left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, b, t);
  3115.  
  3116.     /*Do underflow data box*/
  3117.     c3s(colors[1]);
  3118.     FillRect( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1,
  3119.         left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1, b, t);
  3120.  
  3121.     /*Do the colors in the center*/
  3122.     diff = r - l;
  3123.     start = l;
  3124.     for (k = 2; k < nColors - 1; ++k)
  3125.     {
  3126.         r = (k - 1) * diff / (nColors - 3) + start;
  3127.         c3s(colors[k]);
  3128.         FillRect(l, r, b, t);
  3129.         l = r;
  3130.     }
  3131.  
  3132.     /*Do overflow data box*/
  3133.     c3s(colors[nColors - 1]);
  3134.     FillRect( right - CBRBORDER - CBBOXWIDTH + 1,
  3135.         right - CBRBORDER - 1, b, t);
  3136.     }
  3137.     else
  3138.     {
  3139.     /*It's a color map window, have to set the colors*/
  3140.     int beg;
  3141.  
  3142.     l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  3143.     r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  3144.  
  3145.     SetPalette(palette);
  3146.  
  3147.     var = GetVar(palette, BEGCOLOR);
  3148.     if (!var) return ObjFalse;
  3149.     beg = GetInt(var);
  3150.  
  3151.     /*Do missing data box*/
  3152.     color(beg);
  3153.     FillRect( left + CBLBORDER + CBLTEXTSPACE + 1,
  3154.         left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, b, t);
  3155.  
  3156.     /*Do underflow data box*/
  3157.     color(beg + 1);
  3158.     FillRect( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1,
  3159.         left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1, b, t);
  3160.  
  3161.     /*Do the colors in the center*/
  3162.     diff = r - l;
  3163.     start = l;
  3164.     for (k = 2; k < nColors - 1; ++k)
  3165.     {
  3166.         r = (k - 1) * diff / (nColors - 3) + start;
  3167.         color(beg + k);
  3168.         FillRect(l, r, b, t);
  3169.         l = r;
  3170.     }
  3171.  
  3172.     /*Do overflow data box*/
  3173.     color(beg + nColors - 1);
  3174.     FillRect( right - CBRBORDER - CBBOXWIDTH + 1, 
  3175.         right - CBRBORDER - 1, b, t);
  3176.     }
  3177.  
  3178.  
  3179.     b = t + CBVGAP + 2;
  3180.     t = b + CBCOMPHEIGHT - 1;
  3181.     /*Do 3 components*/
  3182.     for (comp = 2; comp >= 0; --comp)
  3183.     {
  3184.     int height;
  3185.  
  3186.     SetUIColor(UIGRAY62);
  3187.  
  3188.     /*Do missing data box*/
  3189.     height = GetColorComponent(palette, 0, comp) * (CBCOMPHEIGHT - 1) / 255;
  3190.     if (height < CBCOMPHEIGHT - 1)
  3191.     {
  3192.         FillRect( left + CBLBORDER + CBLTEXTSPACE + 1, 
  3193.             left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, 
  3194.             t - CBCOMPHEIGHT + height + 1, t - 1);
  3195.     }
  3196.  
  3197.     /*Do underflow data box*/
  3198.     height = GetColorComponent(palette, 1, comp) * (CBCOMPHEIGHT - 1) / 255;
  3199.     if (height < CBCOMPHEIGHT - 1)
  3200.     {
  3201.         FillRect( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1,
  3202.             left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1,
  3203.             t - CBCOMPHEIGHT + height + 1, t - 1);
  3204.     }
  3205.  
  3206.     /*Do the colors in the center*/
  3207.     l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  3208.     r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  3209.     diff = r - l;
  3210.     start = l;
  3211.     for (k = 2; k < nColors - 1; ++k)
  3212.     {
  3213.         r = (k - 1) * diff / (nColors - 3) + start;
  3214.         height = GetColorComponent(palette, k, comp) * (CBCOMPHEIGHT - 1) / 255;
  3215.         if (height < CBCOMPHEIGHT - 1)
  3216.         {
  3217.         FillRect(l, r, t - CBCOMPHEIGHT + height + 1, t - 1);
  3218.         }
  3219.         l = r;
  3220.     }
  3221.  
  3222.     /*Overflow*/
  3223.     height = GetColorComponent(palette, nColors - 1, comp) * (CBCOMPHEIGHT - 1) / 255;
  3224.     if (height < CBCOMPHEIGHT - 1)
  3225.     {
  3226.         FillRect(right - CBRBORDER - CBBOXWIDTH + 1, 
  3227.         right - CBRBORDER - 1, t - CBCOMPHEIGHT + height + 1, t - 1);
  3228.     }
  3229.     b = t + CBVGAP + 1;
  3230.     t = b + CBCOMPHEIGHT - 1;
  3231.     }
  3232.  
  3233.     /*Now deal with the value*/
  3234.     value = GetValue(colorBar);
  3235.     if (!value)
  3236.     {
  3237.     /*Have to give it a value*/
  3238.     value = NewRealArray(1, 3L);
  3239.     elements = ELEMENTS(value);
  3240.     elements[0] = 0.0;
  3241.     elements[1] = 0.0;
  3242.     elements[2] = 0.0;
  3243.     }
  3244.     else
  3245.     {
  3246.     elements = ELEMENTS(value);
  3247.     }
  3248.  
  3249.     if (elements[0] >= 0.5)
  3250.     {
  3251.     /*Draw the selection in the magnified area*/
  3252.     int dummy;
  3253.  
  3254.     b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP +
  3255.         ((int) (elements[0] - 0.5)) * (CBVGAP + CBCOMPHEIGHT);
  3256.     t = b + CBCOMPHEIGHT;
  3257.  
  3258.     ColorToPixels(&l, &dummy, colorBar, (int) (elements[1] + 0.5));
  3259.     ColorToPixels(&dummy, &r, colorBar, (int) (elements[2] + 0.5));
  3260.  
  3261.     FrameUIRect(l - 1, r + 3, b - 2, t, UIBLACK);
  3262.     FrameUIRect(l - 2, r + 1, b, t + 1, UIYELLOW);
  3263.     FrameUIRect(l - 3, r + 2, b - 1, t + 2, UIYELLOW);
  3264.  
  3265.     /*Draw the expanded range*/
  3266.     if (elements[0] == 1.0)
  3267.     {
  3268.         int c1, c2;
  3269.         /*Draw the full color*/
  3270.         l = left + CBLBORDER + 1;
  3271.         r = right  - CBRBORDER - 1;
  3272.         t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
  3273.         b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP + 4 * CBCOMPHEIGHT
  3274.         + 4 * CBVGAP + 1;
  3275.         if (rgbp)
  3276.         {
  3277.         /*It's in RGB mode, so we don't have to set the palette*/
  3278.  
  3279.         /*Do the colors in the center*/
  3280.         diff = r - l;
  3281.         start = l;
  3282.         c1 = elements[1];
  3283.         c2 = elements[2];
  3284.         
  3285.         for (k = c1; k <= c2; ++k)
  3286.         {
  3287.             r = (k - c1 + 1) * diff / (c2 - c1 + 1) + start;
  3288.             c3s(colors[k]);
  3289.             FillRect(l, r, b, t);
  3290.             l = r;
  3291.         }
  3292.         }
  3293.         else
  3294.         {
  3295.         /*It's a color map window, have to set the colors*/
  3296.         int beg;
  3297.         SetPalette(palette);
  3298.  
  3299.         var = GetVar(palette, BEGCOLOR);
  3300.         if (!var) return ObjFalse;
  3301.         beg = GetInt(var);
  3302.  
  3303.         /*Do the colors in the center*/
  3304.         diff = r - l;
  3305.         start = l;
  3306.         c1 = elements[1];
  3307.         c2 = elements[2];
  3308.         for (k = c1; k <=c2; ++k)
  3309.         {
  3310.             r = (k - c1 + 1) * diff / (c2 - c1 + 1) + start;
  3311.             color(beg + k);
  3312.             FillRect(l, r, b, t);
  3313.             l = r;
  3314.         }
  3315.         }
  3316.     }
  3317.     else
  3318.     {
  3319.         int c1, c2;
  3320.         int height;
  3321.         c1 = elements[1];
  3322.         c2 = elements[2];
  3323.  
  3324.         comp = 4 - ((int) elements[0]);
  3325.  
  3326.         l = left + CBLBORDER + 1;
  3327.         r = right  - CBRBORDER - 1;
  3328.         t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
  3329.         b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP + 4 * CBCOMPHEIGHT
  3330.         + 4 * CBVGAP + 1;
  3331.  
  3332.             ColorModelRect(l, r, b, t, cm, (int) elements[0] - 1);
  3333.  
  3334.         SetUIColor(UIGRAY62);
  3335.         /*Do the colors in the center*/
  3336.         diff = r - l;
  3337.         start = l;
  3338.         for (k = c1; k <= c2; ++k)
  3339.         {
  3340.         r = (k - c1 + 1) * diff / (c2 - c1 + 1) + start;
  3341.         height = GetColorComponent(palette, k, comp) * (t - b) / 255.0 + 0.5;
  3342.         if (height < t - b)
  3343.         {
  3344.             FillRect(l, r, b + height, t);
  3345.         }
  3346.         l = r;
  3347.         }
  3348.     }
  3349.     }    
  3350.  
  3351.     /*Draw the tics at the top*/
  3352.     if (elements[0] > 0.0)
  3353.     {
  3354.     real start, finish, halfSpace;
  3355.     l = left + CBLBORDER + 1;
  3356.     r = right - CBRBORDER - 1;
  3357.     t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
  3358.     b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP +  4 * CBCOMPHEIGHT + 4 * CBVGAP + 1;
  3359.  
  3360.     if  (elements[2] >= elements[1])
  3361.     {
  3362.         /*It's a range*/
  3363.  
  3364.         halfSpace = (minmax[1] - minmax[0]) / (nColors - 4) * 0.5;
  3365.         start = GetColorValue(palette, (int) elements[1]) - halfSpace;
  3366.         finish = GetColorValue(palette, (int) elements[2]) + halfSpace;
  3367.         ddiff = finish - start;
  3368.  
  3369.         CalcGoodSteps(ddiff,
  3370.               r - l,
  3371.               CBSTEPPIXELS,
  3372.               &majorWidth, &nTics);
  3373.  
  3374.         minorWidth = majorWidth / nTics;
  3375.  
  3376.         /*Minor and major tics first*/
  3377.         temp = start / majorWidth;
  3378.         curValue = temp * majorWidth;
  3379.         while (curValue > start)
  3380.         {
  3381.          curValue -= majorWidth;
  3382.         }
  3383.         k = 0;
  3384.  
  3385.         while (curValue < start)
  3386.         {
  3387.         ++k;
  3388.         if (k >= nTics) k = 0;
  3389.  
  3390.         curValue += minorWidth;
  3391.         }
  3392.  
  3393.         SetUIFont(CBBIGTEXTFONT);
  3394.  
  3395.         /*Now actually draw them*/
  3396.         if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  3397.         while (curValue <= finish + ddiff * 1.0E-6)
  3398.         {
  3399.         pixel = l + (curValue - start) * (r - l) / (ddiff);
  3400.         if (k == 0)
  3401.         {
  3402.             /*Major tic*/
  3403.             DrawUILine(pixel,
  3404.                 top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP,
  3405.                 pixel,
  3406.                 top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP + CBMAJORTICLEN,
  3407.                 UIBLACK);
  3408.  
  3409.             sprintf(tempStr, "%lg", curValue);
  3410.             {
  3411.             DrawAString(CENTERALIGN, pixel, top - CBTBORDER - CBTEXTDOWN, tempStr);
  3412.             }
  3413.         }
  3414.         else
  3415.         {
  3416.             /*Minor tic*/
  3417.             DrawUILine(pixel,
  3418.                 top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP,
  3419.                 pixel,
  3420.                 top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP + CBMAJORTICLEN / 2,
  3421.                 UIBLACK);
  3422.         }
  3423.  
  3424.         curValue += minorWidth;
  3425.         if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  3426.         ++k;
  3427.         if (k >= nTics) k = 0;
  3428.         }
  3429.  
  3430.         /*Draw the function box, if any*/
  3431.         var = GetVar(colorBar, FUNCTIONBOX);
  3432.         if (var)
  3433.         {
  3434.         real *elements;
  3435.         elements = ELEMENTS(var);
  3436.  
  3437.         SetClipRect(left + 3, right - 3, bottom + 3, top - 3);
  3438.  
  3439.         DrawFunctionBox(elements, l, r, b, t, start, finish);
  3440.  
  3441.         RestoreClipRect();
  3442.         }
  3443.     }
  3444.     }
  3445.  
  3446. #endif
  3447.     return ObjTrue;
  3448. }
  3449.  
  3450. #ifdef PROTO
  3451. ObjPtr SetFunctionBox(ObjPtr colorBar, ObjPtr functionBox)
  3452. #else
  3453. ObjPtr SetFunctionBox(colorBar, functionBox)
  3454. ObjPtr colorBar;
  3455. ObjPtr functionBox;
  3456. #endif
  3457. /*Sets the FUNCTIONBOX of colorBar to functionBox, also logs*/
  3458. {
  3459.     real *elements;
  3460.     ObjPtr repObj;
  3461.     if (functionBox && (!IsRealArray(functionBox) || RANK(functionBox) != 1 || 
  3462.     DIMS(functionBox)[0] != 4))
  3463.     {
  3464.     ReportError("SetFunctionBox", "Bad value given");
  3465.     return ObjFalse;
  3466.     }
  3467.     repObj = GetPaletteVar("SetFunctionBox", colorBar, REPOBJ);
  3468.     if (!repObj)
  3469.     {
  3470.     return ObjFalse;
  3471.     }
  3472.     if (functionBox)
  3473.     {
  3474.     elements = ELEMENTS(functionBox);
  3475.     if (elements[2] < -0.5 || elements[2] >= 255.5 ||
  3476.         elements[3] < -0.5 || elements[3] >= 255.5 ||
  3477.         elements[2] > elements[3] ||
  3478.         elements[0] > elements[1])
  3479.     {
  3480.         ReportError("SetFunctionBox", "Value out of range");
  3481.         return ObjFalse;
  3482.     }
  3483.     }
  3484.  
  3485.     SetVar(colorBar, FUNCTIONBOX, functionBox);
  3486.  
  3487.     if (logging)
  3488.     {
  3489.     char cmd[256];
  3490.     char *s;
  3491.  
  3492.     sprintf(cmd, "set functionbox ");
  3493.     s = &(cmd[0]);
  3494.     while (*s) ++s;
  3495.     MakeObjectName(s, colorBar);
  3496.     while (*s) ++s;
  3497.     *s++ = ' ';
  3498.     PrintScriptObject(s, functionBox);
  3499.     while (*s) ++s;
  3500.     *s++ = '\n';
  3501.     *s = 0;
  3502.     Log(cmd);
  3503.     }
  3504.     return ObjTrue;
  3505. }
  3506.  
  3507. #ifdef PROTO
  3508. void LogColorChange(ObjPtr colorBar, short3 *colors, int newColor)
  3509. #else
  3510. void LogColorChange(colorBar, colors, newColor)
  3511. ObjPtr colorBar;
  3512. short3 *colors;
  3513. int newColor;
  3514. #endif
  3515. /*Logs a change to colors[newColor] within colorBar*/
  3516. {
  3517.     if (logging)
  3518.     {
  3519.     char cmd[256];
  3520.     char *s;
  3521.  
  3522.     sprintf(cmd, "set color ");
  3523.     s = &(cmd[0]);
  3524.     while (*s) ++s;
  3525.     MakeObjectName(s, colorBar);
  3526.     while (*s) ++s;
  3527.     *s++ = ' ';
  3528.     sprintf(s, "%d %d %d %d\n", newColor, colors[newColor][0], 
  3529.             colors[newColor][1], colors[newColor][2]);
  3530.     Log(cmd);
  3531.     }
  3532. }
  3533.  
  3534. #ifdef PROTO
  3535. ObjPtr SetColorBarColor(ObjPtr colorBar, int whichColor, int r, int g, int b)
  3536. #else
  3537. ObjPtr SetColorBarColor(colorBar, whichColor, r, g, b)
  3538. ObjPtr colorBar;
  3539. int whichColor, r, g, b;
  3540. #endif
  3541. /*Sets color whichColor from inside a color bar*/
  3542. {
  3543.     ObjPtr palette;
  3544.     short3 *colors;
  3545.     ObjPtr var;
  3546.  
  3547.     palette = GetPaletteVar("SetColorBarColor", colorBar, REPOBJ);
  3548.     if (!palette)
  3549.     {
  3550.     return ObjFalse;
  3551.     }
  3552.  
  3553.     /*DIKEO destructive!   Change this later!*/
  3554.     MakeVar(palette, COLORS);
  3555.     var = GetVar(palette, COLORS);
  3556.     if (!colors) return ObjFalse;
  3557.     colors = ELEMENTS(var);
  3558.     colors[whichColor][0] = r;
  3559.     colors[whichColor][1] = g;
  3560.     colors[whichColor][2] = b;
  3561.  
  3562.     ImInvalid(colorBar);
  3563.     LogColorChange(colorBar, colors, whichColor);
  3564.     ChangedValue(colorBar);
  3565.  
  3566. #ifdef GRAPHICS
  3567.     MapPaletteColors(palette, whichColor, whichColor);
  3568. #endif
  3569.     SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  3570.     ForAllVisWindows(ImInvalid);
  3571.     return ObjTrue;
  3572. }
  3573.  
  3574. static ObjPtr PressColorBar(colorBar, x, y, flags)
  3575. ObjPtr colorBar;
  3576. int x, y;
  3577. long flags;
  3578. /*Does a press in a color bar beginning at x and y.  Returns
  3579.   true iff the press really was in the control.*/
  3580. {
  3581. #ifdef INTERACTIVE
  3582.     int left, right, bottom, top;
  3583.     int l, r, b, t;
  3584.     int k;
  3585.     int cm;
  3586.     Bool doubleP;
  3587.     int nColors;
  3588.     ObjPtr var;
  3589.  
  3590.     Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
  3591.  
  3592.     if (x >= left && x <= right && y >= bottom && y <= top)
  3593.     {
  3594.     real val[3];
  3595.     ObjPtr value, var;
  3596.     real *origVal;
  3597.     ObjPtr palette;
  3598.     /*Hey!  It really was a click in the color bar*/
  3599.  
  3600.     if (TOOL(flags) == T_HELP)
  3601.     {
  3602.         ContextHelp(colorBar);
  3603.         return ObjTrue;
  3604.     }
  3605.  
  3606.     b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP;
  3607.     if (y < b)
  3608.     {
  3609.         /*Click below*/
  3610.         val[0] = val[1] = val[2] = 0.0;
  3611.         value = NewRealArray(1, 3L);
  3612.         CArray2Array(value, val);
  3613.         SetValue(colorBar, value);
  3614.         return ObjTrue;
  3615.     }
  3616.  
  3617.     doubleP = IsDoubleBuf(selWinInfo) ? true : false;
  3618.  
  3619.     MakeMeCurrent(colorBar);
  3620.  
  3621.     SaveForUndo(colorBar);
  3622.  
  3623.     /*Get current value*/
  3624.     value = GetFixedArrayVar("PressColorBar", colorBar, VALUE, 1, 3L);
  3625.     if (!value)
  3626.     {
  3627.         return ObjFalse;
  3628.     }
  3629.  
  3630.     origVal = (real *) ELEMENTS(value);
  3631.  
  3632.     palette = GetPaletteVar("PressColorBar", colorBar, REPOBJ);
  3633.     if (!palette)
  3634.     {
  3635.         return ObjFalse;
  3636.     }
  3637.  
  3638.     var = GetIntVar("PressColorBar", palette, NCOLORS);
  3639.     if (!var) return;
  3640.     nColors = GetInt(var);
  3641.  
  3642.     /*Get the color model*/
  3643.     var = GetIntVar("PressColorBar", palette, COLORMODEL);
  3644.     if (!var)
  3645.     {
  3646.         return ObjFalse;
  3647.     }
  3648.     cm = GetInt(var);
  3649.  
  3650.     /*See if it's in one of the components or full color*/
  3651.     for (k = 0; k < 4; ++k)
  3652.     {
  3653.         t = b + CBCOMPHEIGHT;
  3654.         if (y <= t && y >= b)
  3655.         {
  3656.         ObjPtr radio;
  3657.         int newX, newY;
  3658.         int startColor;
  3659.         int lastColor;
  3660.         int newColor;
  3661.         Bool inp;            /*True if inside*/
  3662.         int dummy;            /*Dummy for colorToPixels*/
  3663.         int cb, ct, cl, cr;        /*b, t, l, r for cursor*/
  3664.         
  3665.  
  3666.         /*It's a press in track k*/
  3667.         InhibitLogging(true);
  3668.  
  3669.         if ((flags & F_SHIFTDOWN) || TOOL(flags) == T_ROTATE)
  3670.         {
  3671.             /*Shift click, determine start from farthest*/
  3672.             newColor = PixelToColor(colorBar, x);
  3673.             if (ABS(newColor - origVal[2]) < ABS(newColor - origVal[1]))
  3674.             {
  3675.             startColor = origVal[1];
  3676.             }
  3677.             else
  3678.             {
  3679.             startColor = origVal[2];
  3680.             }
  3681.         }
  3682.         else
  3683.         {
  3684.             startColor = PixelToColor(colorBar, x);
  3685.         }
  3686.         lastColor = -1;
  3687.  
  3688.         val[0] = (real) (k + 1);
  3689.  
  3690.         inp = true;
  3691.  
  3692.         /*Set the edit tool to free form*/
  3693.         ResetColorBarTools(colorBar);
  3694.  
  3695.         if (!doubleP)
  3696.         {
  3697.             DrawSkeleton(true);
  3698.  
  3699.             cb = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP +
  3700.             ((int) (val[0] - 0.5)) * (CBVGAP + CBCOMPHEIGHT);
  3701.             ct = b + CBCOMPHEIGHT;
  3702.  
  3703.             ColorToPixels(&cl, &dummy, colorBar, (int) (val[1] + 0.5));
  3704.             ColorToPixels(&dummy, &cr, colorBar, (int) (val[2] + 0.5));
  3705.  
  3706.             FrameUIRect(cl - 2, cr + 1, cb, ct + 1, UIRED);
  3707.             FrameUIRect(cl - 3, cr + 2, cb - 1, ct + 2, UIRED);
  3708.         }
  3709.  
  3710.         while (Mouse(&newX, &newY))
  3711.         {
  3712.             if (newY > t + SLOP ||
  3713.             newY < b - SLOP ||
  3714.             newX < left - SLOP ||
  3715.             newX > right + SLOP)
  3716.             {
  3717.             /*It's outside*/
  3718.             if (inp)
  3719.             {
  3720.                 /*Transition from in to out*/
  3721.                 SetVar(colorBar, VALUE, value);
  3722.                 inp = false;
  3723.                 lastColor = -1;
  3724.                 if (doubleP)
  3725.                 {
  3726.                 DrawMe(colorBar);
  3727.                 }
  3728.                 else
  3729.                 {
  3730.                 EraseAll();
  3731.                 }
  3732.             }
  3733.             }
  3734.             else
  3735.             {
  3736.             /*It's inside*/
  3737.             if (!inp)
  3738.             {
  3739.                 /*Transition from out to in*/
  3740.                 inp = true;
  3741.             }
  3742.             newColor = PixelToColor(colorBar, newX);
  3743.             if (newColor != lastColor)
  3744.             {
  3745.                 ObjPtr var;
  3746.  
  3747.                 /*It's a new color, set it*/
  3748.                 if (newColor >= startColor)
  3749.                 {
  3750.                 val[1] = (real) startColor;
  3751.                 val[2] = (real) newColor;
  3752.                 }
  3753.                 else
  3754.                 {
  3755.                 val[2] = (real) startColor;
  3756.                 val[1] = (real) newColor;
  3757.                 }
  3758.                  var = NewRealArray(1, 3L);
  3759.                 CArray2Array(var, val);
  3760.                 SetVar(colorBar, VALUE, var);
  3761.                 if (doubleP)
  3762.                 {
  3763.                 DrawMe(colorBar);
  3764.                 }
  3765.                 else
  3766.                 {
  3767.                 ColorToPixels(&cl, &dummy, colorBar, (int) (val[1] + 0.5));
  3768.                 ColorToPixels(&dummy, &cr, colorBar, (int) (val[2] + 0.5));
  3769.                 EraseAll();
  3770.                 FrameUIRect(cl - 2, cr + 1, cb, ct + 1, UIRED);
  3771.                 FrameUIRect(cl - 3, cr + 2, cb - 1, ct + 2, UIRED);
  3772.                 }
  3773.                 lastColor = newColor;
  3774.             }
  3775.             }
  3776.         }
  3777.         if (!doubleP)
  3778.         {
  3779.             DrawSkeleton(false);
  3780.         }
  3781.         ChangedValue(colorBar);
  3782.         ImInvalid(colorBar);
  3783.         InhibitLogging(false);
  3784.         LogControl(colorBar);
  3785.         return ObjTrue;
  3786.         }
  3787.         b = t + CBVGAP;
  3788.     }
  3789.  
  3790.     /*It wasn't in a component, maybe it's in the readout*/
  3791.     t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
  3792.     l = left + CBLBORDER + 1;
  3793.     r = right - CBRBORDER - 1;
  3794.     if (origVal[0] > 1.0 &&
  3795.         y >= b - SLOP && y <= t + SLOP && x >= l - SLOP && x <= r + SLOP)
  3796.     {
  3797.         /*It is!  Do stuff based on edit mode*/
  3798.         int editMode;
  3799.         int lastColor, lastAmp;
  3800.         ObjPtr palette;
  3801.         int index1, index2;
  3802.         int k;
  3803.         int comp;
  3804.         short3 *colors;
  3805.         int newX, newY, newColor, newAmp;
  3806.         ObjPtr panel, button;
  3807.         ObjPtr var;
  3808.  
  3809.         palette = GetPaletteVar("PressColorBar", colorBar, REPOBJ);
  3810.         if (!palette)
  3811.         {
  3812.         return ObjFalse;
  3813.         }
  3814.  
  3815.         MakeVar(palette, COLORS);
  3816.         var = GetVar(palette, COLORS);
  3817.         if (!var)
  3818.         {
  3819.         return ObjFalse;
  3820.         }
  3821.         colors = ELEMENTS(var);
  3822.  
  3823.         comp = 4 - origVal[0];
  3824.  
  3825.         var = GetIntVar("PressColorBar", colorBar, EDITMODE);
  3826.         if (!var)
  3827.         {
  3828.         return ObjFalse;
  3829.         }
  3830.         editMode = GetInt(var);
  3831.  
  3832.         index1 = origVal[1] + 0.5;
  3833.         index2 = origVal[2] + 0.5;
  3834.  
  3835.         panel = GetVar(colorBar, PARENT);
  3836.         if (panel)
  3837.         {
  3838.         button = GetVar(panel, KEEPBUTTON);
  3839.         if (button)
  3840.         {
  3841.             ActivateButton(button, true);
  3842.         }
  3843.         button = GetVar(panel, REVERTBUTTON);
  3844.         if (button)
  3845.         {
  3846.             ActivateButton(button, true);
  3847.         }
  3848.         }
  3849.  
  3850.         if (editMode == PT_FREEFORM)
  3851.         {
  3852.         int firstAltered, lastAltered;
  3853.         Bool constrainX, constrainY;
  3854.         /*Free form*/
  3855.         lastColor = lastAmp = -1;
  3856.  
  3857.         firstAltered = index2 + 1;
  3858.         lastAltered = index1 - 1;
  3859.  
  3860.         constrainX = constrainY = false;
  3861.  
  3862.         while (Mouse(&newX, &newY))
  3863.         {
  3864.             if (newX >= l - SLOP && newX <= r + SLOP && newY >= b - SLOP && newY <= t + SLOP)
  3865.             {
  3866.             
  3867.             if (flags & F_SHIFTDOWN)
  3868.             {
  3869.                 if (!constrainX && !constrainY)
  3870.                 {
  3871.                 int xDiff, yDiff;
  3872.  
  3873.                 /*Must make some constraints*/
  3874.                 xDiff = ABS(newX - x);
  3875.                 yDiff = ABS(newY - y);
  3876.                 if (xDiff >= MINCONSTRAINT &&
  3877.                     yDiff >= MINCONSTRAINT)
  3878.                 {
  3879.                     if (yDiff > xDiff)
  3880.                     {
  3881.                     constrainX = true;
  3882.                     }
  3883.                     else
  3884.                     {
  3885.                     constrainY = true;
  3886.                     }
  3887.                 }
  3888.                 }
  3889.                 if (constrainX) newX = x;
  3890.                 if (constrainY) newY = y;
  3891.             }
  3892.  
  3893.             /*Calculate newAmp*/
  3894.             newAmp = ((newY - b) + 0.5) * 255.0 / (real) (t - b - 1);
  3895.             if (newAmp < 0) newAmp = 0;
  3896.             else if (newAmp > 255) newAmp = 255;
  3897.  
  3898.             /*Calculate newColor*/
  3899.             newColor = index1 + ((real) newX - l) * ((real) index2 - index1 + 1) / ((real) (r - l - 1));            
  3900.             if (newColor < index1) newColor = index1;
  3901.             else if (newColor > index2) newColor = index2;
  3902.  
  3903.             if (newColor < firstAltered)
  3904.             {
  3905.                 firstAltered = newColor;
  3906.             }
  3907.             if (newColor > lastAltered)
  3908.             {
  3909.                 lastAltered = newColor;
  3910.             }
  3911.  
  3912.             if (newAmp != lastAmp || newColor != lastColor)
  3913.             {
  3914.                 /*Set the new color to be correct*/
  3915.                 
  3916.                 if (lastColor <= -1 || lastColor == newColor)
  3917.                 {
  3918.                 /*New in this range, just set this color*/
  3919.                 SetColorComponent(palette, newColor, comp, newAmp);
  3920. #ifdef GRAPHICS
  3921.                 MapPaletteColors(palette, newColor, newColor);
  3922. #endif
  3923.                 }
  3924.                 else if (newColor > lastColor)
  3925.                 {
  3926.                 int nc;
  3927.                 /*Linearly interpolate up to this color*/
  3928.                 for (k = lastColor + 1; k <= newColor; ++k)
  3929.                 {
  3930.                     nc = ((newColor - k) * lastAmp +
  3931.                       (k - lastColor) * newAmp) / 
  3932.                         (newColor - lastColor);
  3933.                     if (nc < 0) nc = 0;
  3934.                     else if (nc > 255) nc = 255;
  3935.  
  3936.                     SetColorComponent(palette, k, comp, nc);
  3937.  
  3938.                 }
  3939. #ifdef GRAPHICS
  3940.                 MapPaletteColors(palette, lastColor, newColor);
  3941. #endif
  3942.                 }
  3943.                 else if (newColor < lastColor)
  3944.                 {
  3945.                 int nc;
  3946.                 /*Linearly interpolate down to this color*/
  3947.                 for (k = lastColor - 1; k >= newColor; --k)
  3948.                 {
  3949.                     nc = ((k - newColor) * lastAmp +
  3950.                       (lastColor - k) * newAmp) / 
  3951.                         (lastColor - newColor);
  3952.                     if (nc < 0) nc = 0;
  3953.                     else if (nc > 255) nc = 255;
  3954.  
  3955.                     SetColorComponent(palette, k, comp, nc);
  3956.                 }
  3957. #ifdef GRAPHICS
  3958.                 MapPaletteColors(palette, lastColor, newColor);
  3959. #endif
  3960.                 }
  3961.                 CopyComponentsToColors(palette);
  3962.                 DrawMeInBounds(colorBar, left + 3, right - 3, bottom + 3, top - 3);
  3963.                  lastAmp = newAmp;
  3964.                 lastColor = newColor;
  3965.             }
  3966.             }
  3967.             else
  3968.             {
  3969.             lastColor = lastAmp = -1;
  3970.             }
  3971.         }
  3972.         for (k = firstAltered; k <= lastAltered; ++k)
  3973.         {
  3974.             LogColorChange(colorBar, colors, k);
  3975.         }
  3976.         ChangedValue(colorBar);
  3977.         SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  3978.         ForAllVisWindows(ImInvalid);
  3979.         }
  3980.         else
  3981.         {
  3982.         /*It's a tool*/
  3983.         ObjPtr toolBounds;
  3984.         int boxL, boxR, boxB, boxT;
  3985.         int xOffset, yOffset;
  3986.         double start, finish, ddiff, halfSpace;
  3987.         real *elements;
  3988.         real newElements[4];
  3989.         int whichMove = 0;
  3990.         real lastSide, nextSide;
  3991.         double majorWidth, minorWidth;
  3992.         int nTics;
  3993.         long temp;
  3994.         real *minmax;
  3995.  
  3996. #define MOVEBOXTOP     1
  3997. #define MOVEBOXBOTTOM    2
  3998. #define MOVEBOXLEFT    3
  3999. #define MOVEBOXRIGHT    4
  4000. #define MOVEBOXLR    5
  4001.  
  4002.         var = GetVar(palette, MINMAX);
  4003.         minmax = ELEMENTS(var);
  4004.         halfSpace = (minmax[1] - minmax[0]) / (nColors - 4) * 0.5;
  4005.         start = GetColorValue(palette, index1) - halfSpace;
  4006.         finish = GetColorValue(palette, index2) + halfSpace;
  4007.         ddiff = finish - start;
  4008.  
  4009.         toolBounds = GetFixedArrayVar("PressColorBar", colorBar, FUNCTIONBOX, 1, 4L);
  4010.         if (!toolBounds)
  4011.         {
  4012.             return ObjFalse;
  4013.         }
  4014.         elements = ELEMENTS(toolBounds);
  4015.     
  4016.         boxL = l + (elements[0] - start) * (r - l) / (ddiff);
  4017.         boxR = l + (elements[1] - start) * (r - l) / (ddiff);
  4018.         boxB = b + elements[2] * (t - b) / 255.0;
  4019.         boxT = b + elements[3] * (t - b) / 255.0;
  4020.  
  4021.         if (!doubleP)
  4022.         {
  4023.             DrawSkeleton(true);
  4024.         }
  4025.  
  4026.         /*Figure out which side is clicked on*/
  4027.  
  4028.         whichMove = 0;
  4029.         if (y >= boxB - (CBHANDLESIZE + 2) && y <= boxT + (CBHANDLESIZE + 2))
  4030.         {
  4031.             if (x >= boxL - (CBHANDLESIZE + 2) && x <= boxL)
  4032.             {
  4033.             whichMove = MOVEBOXLEFT;
  4034.             xOffset = x - boxL;
  4035.             }
  4036.             else if (x >= boxR && x <= boxR + (CBHANDLESIZE + 2))
  4037.             {
  4038.             whichMove = MOVEBOXRIGHT;
  4039.             xOffset = x - boxR;
  4040.             }
  4041.         }
  4042.         if (x >= boxL - (CBHANDLESIZE + 2) && x <= boxR + (CBHANDLESIZE + 2))
  4043.         {
  4044.             if (y >= boxB - (CBHANDLESIZE + 2) && y <= boxB)
  4045.             {
  4046.             whichMove = MOVEBOXBOTTOM;
  4047.             yOffset = y - boxB;
  4048.             }
  4049.             else if (y >= boxT && y <= boxT + (CBHANDLESIZE + 2))
  4050.             {
  4051.             whichMove = MOVEBOXTOP;
  4052.             yOffset = y - boxT;
  4053.             }
  4054.         } 
  4055.         if (!whichMove)
  4056.         {
  4057.             whichMove = MOVEBOXLR;
  4058.             xOffset = x - boxL;
  4059.             yOffset = y - (boxT + boxB) / 2;
  4060.         }
  4061.  
  4062.         newElements[0] = elements[0];
  4063.         newElements[1] = elements[1];
  4064.         newElements[2] = elements[2];
  4065.         newElements[3] = elements[3];
  4066.  
  4067.         if (flags & F_SHIFTDOWN)
  4068.         {
  4069.             /*Constrained motion, have to calc constraint stuff*/
  4070.             halfSpace = (minmax[1] - minmax[0]) / (nColors - 4) * 0.5;
  4071.             start = GetColorValue(palette, index1) - halfSpace;
  4072.             finish = GetColorValue(palette, index2) + halfSpace;
  4073.             ddiff = finish - start;
  4074.     
  4075.             CalcGoodSteps(ddiff,
  4076.                   r - l,
  4077.                   CBSTEPPIXELS,
  4078.                   &majorWidth, &nTics);
  4079.             minorWidth = majorWidth / nTics;
  4080.         }
  4081.  
  4082.         /*Now do it*/
  4083.         if (whichMove == MOVEBOXLEFT || whichMove == MOVEBOXRIGHT)
  4084.         {
  4085.             lastSide = newElements[whichMove == MOVEBOXLEFT ? 0 : 1];
  4086.             while (Mouse(&newX, &newY))
  4087.             {        
  4088.             nextSide = start +
  4089.                 (newX - xOffset - l) * (finish - start) / (r - l);
  4090.             if (flags & F_SHIFTDOWN)
  4091.             {
  4092.                 /*Constrain*/
  4093.                 temp = nextSide / minorWidth + 0.5;
  4094.                 nextSide = temp * minorWidth;
  4095.             }
  4096.  
  4097.             if (nextSide != lastSide)
  4098.             {
  4099.                 /*Change it*/
  4100.  
  4101.                 newElements[whichMove == MOVEBOXLEFT ? 0 : 1] = nextSide;
  4102.                 if (newElements[1] > newElements[0])
  4103.                 {
  4104.                 toolBounds = NewRealArray(1, 4L);
  4105.                 CArray2Array(toolBounds, newElements);
  4106.                 SetFunctionBox(colorBar, toolBounds);
  4107.                 InhibitLogging(true);
  4108.                 ImposeColorFunction(colorBar);
  4109.                 InhibitLogging(false);
  4110.                 if (doubleP)
  4111.                 {
  4112.                     DrawMe(colorBar);
  4113.                 }
  4114.                 else
  4115.                 {
  4116.                     EraseAll();
  4117.                     DrawFunctionBox(newElements, l, r, b, t, start, finish);
  4118.                 }
  4119.                 lastSide = nextSide;
  4120.                 }
  4121.             }
  4122.             }
  4123.         }
  4124.         else if (whichMove == MOVEBOXTOP || whichMove == MOVEBOXBOTTOM)
  4125.         {
  4126.             lastAmp = newElements[whichMove == MOVEBOXBOTTOM ? 2 : 3] + 0.5;
  4127.             while (Mouse(&newX, &newY))
  4128.             {        
  4129.             newAmp = ((newY - yOffset - b) + 0.5) * 255.0 / (real) (t - b - 1);
  4130.             if (newAmp < 0) newAmp = 0;
  4131.             else if (newAmp > 255) newAmp = 255;
  4132.             if (newAmp != lastAmp)
  4133.             {
  4134.                 /*Change it*/
  4135.  
  4136.                 newElements[whichMove == MOVEBOXBOTTOM ? 2 : 3] = newAmp;
  4137.                 if (newElements[3] > newElements[2])
  4138.                 {
  4139.                 toolBounds = NewRealArray(1, 4L);
  4140.                 CArray2Array(toolBounds, newElements);
  4141.                 SetFunctionBox(colorBar, toolBounds);
  4142.                 InhibitLogging(true);
  4143.                 ImposeColorFunction(colorBar);
  4144.                 InhibitLogging(false);
  4145.                 if (doubleP)
  4146.                 {
  4147.                     DrawMe(colorBar);
  4148.                 }
  4149.                 else
  4150.                 {
  4151.                     EraseAll();
  4152.                     DrawFunctionBox(newElements, l, r, b, t, start, finish);
  4153.                 }
  4154.                 lastAmp = newAmp;
  4155.                 }
  4156.             }
  4157.             }
  4158.         }
  4159.         if (whichMove == MOVEBOXLR)
  4160.         {
  4161.             lastSide = newElements[0];
  4162.             while (Mouse(&newX, &newY))
  4163.             {        
  4164.             nextSide = start +
  4165.                 (newX - xOffset - l) * (finish - start) / (r - l);
  4166.             if (flags & F_SHIFTDOWN)
  4167.             {
  4168.                 /*Constrain*/
  4169.                 temp = nextSide / minorWidth + 0.5;
  4170.                 nextSide = temp * minorWidth;
  4171.             }
  4172.             if (nextSide != lastSide)
  4173.             {
  4174.                 /*Change it*/
  4175.  
  4176.                 newElements[0] = nextSide;
  4177.                 newElements[1] = nextSide + elements[1] - elements[0];
  4178.                 if (newElements[1] > newElements[0])
  4179.                 {
  4180.                 toolBounds = NewRealArray(1, 4L);
  4181.                 CArray2Array(toolBounds, newElements);
  4182.                 SetFunctionBox(colorBar, toolBounds);
  4183.                 InhibitLogging(true);
  4184.                 ImposeColorFunction(colorBar);
  4185.                 InhibitLogging(false);
  4186.                 if (doubleP)
  4187.                 {
  4188.                     DrawMe(colorBar);
  4189.                 }
  4190.                 else
  4191.                 {
  4192.                     EraseAll();
  4193.                     DrawFunctionBox(newElements, l, r, b, t, start, finish);
  4194.                 }
  4195.                 lastSide = nextSide;
  4196.                 }
  4197.             }
  4198.             }
  4199.         }
  4200.         if (!doubleP)
  4201.         {
  4202.             DrawSkeleton(false);
  4203.         }
  4204.         ChangedValue(colorBar);
  4205.         SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  4206.         ForAllVisWindows(ImInvalid);
  4207.         }
  4208.     }
  4209.  
  4210.     return ObjTrue;
  4211.     }
  4212.     else
  4213.     {
  4214.     return ObjFalse;
  4215.     }
  4216. #else
  4217.     return ObjFalse;
  4218. #endif
  4219. }
  4220.  
  4221. #ifdef PROTO
  4222. ObjPtr NewColorBar(int left, int right, int bottom, int top, char *name)
  4223. #else
  4224. ObjPtr NewColorBar(left, right, bottom, top, name)
  4225. int left, right, bottom, top;
  4226. char *name;
  4227. #endif
  4228. /*Makes a new hue/saturation control in left, right, bottom, top*/
  4229. {
  4230.     ObjPtr retVal;
  4231.     ObjPtr value;
  4232.     
  4233.     retVal = NewObject(colorBarClass, 0);
  4234.     Set2DIntBounds(retVal, left, right, bottom, top);
  4235.     SetVar(retVal, NAME, NewString(name));
  4236.     SetVar(retVal, TYPESTRING, NewString("color bar control"));
  4237.     value = NewRealArray(1, 3L);
  4238.     ((real *) ELEMENTS(value))[0] = 1.0;
  4239.     ((real *) ELEMENTS(value))[1] = 0.0;
  4240.     ((real *) ELEMENTS(value))[1] = 0.0;
  4241.     SetVar(retVal, VALUE, value);
  4242.     return retVal;
  4243. }
  4244.  
  4245. #ifdef PROTO
  4246. static void ChoosePaletteSliderValue(ObjPtr slider, ObjPtr palette, 
  4247.         int component, int index1, int index2)
  4248. #else
  4249. static void ChoosePaletteSliderValue(slider, palette, component, index1, index2)
  4250. ObjPtr slider;
  4251. ObjPtr palette;
  4252. int index1, index2, component;
  4253. #endif
  4254. /*Chooses a value for the slider based on colors index1 through index2 of
  4255.   palette.  Component is 0 for rgb, 1 for r, 2 for g, and 3 for b, */
  4256. {
  4257.     real min, max, testVal;
  4258.     short3 *colors;
  4259.     real hsv[3];
  4260.     int k;
  4261.     ObjPtr var;
  4262.  
  4263.     MakeVar(palette, COLORS);
  4264.     var = GetVar(palette, COLORS);
  4265.     if (!var) return;
  4266.     colors = ELEMENTS(var);
  4267.  
  4268.     min = 1.0;
  4269.     max = 0.0;
  4270.     if (component)
  4271.     {
  4272.     for (k = index1; k <= index2; ++k)
  4273.     {
  4274.         testVal = ((real) GetColorComponent(palette, k, component - 1)) / 255.0;
  4275.         if (testVal < min)
  4276.         {
  4277.         min = testVal;
  4278.         }
  4279.         if (testVal > max)
  4280.         {
  4281.         max = testVal;
  4282.         }
  4283.     }    
  4284.     }
  4285.     else
  4286.     {
  4287.     for (k = index1; k <= index2; ++k)
  4288.     {
  4289.         RGB2HSV(&(hsv[0]), &(hsv[1]), &(hsv[2]),
  4290.         ((real) colors[k][0]) / 255.0, 
  4291.         ((real) colors[k][1]) / 255.0, 
  4292.         ((real) colors[k][2]) / 255.0);
  4293.         testVal = hsv[2];
  4294.         if (testVal < min)
  4295.         {
  4296.         min = testVal;
  4297.         }
  4298.         if (testVal > max)
  4299.         {
  4300.         max = testVal;
  4301.         }
  4302.     }
  4303.     }
  4304.     testVal = (min + max) * 0.5;
  4305.     if (testVal < 0.0) testVal = 0.0;
  4306.     if (testVal > 1.0) testVal = 1.0;
  4307.     SetSliderValue(slider, testVal);
  4308.     SetVar(slider, INITVALUE, NewReal(testVal));
  4309.     SetVar(slider, TEMPPALETTE, CloneObject(palette));
  4310. }
  4311.  
  4312. static ObjPtr ChangePaletteBar(colorBar)
  4313. ObjPtr colorBar;
  4314. /*Changed value for a color bar that controls a palette*/
  4315. {
  4316.     ObjPtr colorWheel, slider, button, buttons;
  4317.     ThingListPtr buttonList;
  4318.     ObjPtr palette;
  4319.     ObjPtr value, newValue;
  4320.     FuncTyp changedValue;
  4321.     real hsv[3];
  4322.     short3 *colors;
  4323.     int index;
  4324.     real *elements;
  4325.  
  4326.     value = GetFixedArrayVar("ChangePaletteBar", colorBar, VALUE, 1, 3L);
  4327.     colorWheel = GetObjectVar("ChangePaletteBar", colorBar, COLORWHEEL);
  4328.     palette = GetPaletteVar("ChangePaletteBar", colorBar, REPOBJ);
  4329.     slider = GetObjectVar("ChangePaletteBar", colorBar, SLIDER);
  4330.  
  4331.     if (!colorWheel || !palette || !value || !slider)
  4332.     {
  4333.     return ObjFalse;
  4334.     }
  4335.  
  4336.     elements = ELEMENTS(value);
  4337.     if (elements[0] == 1.0)
  4338.     {
  4339.     /*Active color wheel*/
  4340.     ActivateColorWheel(colorWheel, true);
  4341.     if (elements[1] == elements[2])
  4342.     {
  4343.         /*Give it a value*/
  4344.         ObjPtr var;
  4345.         MakeVar(palette, COLORS);
  4346.         var = GetVar(palette, COLORS);
  4347.         if (!var) return ObjFalse;
  4348.         colors = ELEMENTS(var);
  4349.  
  4350.         /*Update the left slider and color wheel*/
  4351.         index = elements[1];
  4352.  
  4353.         RGB2HSV(&(hsv[0]), &(hsv[1]), &(hsv[2]),
  4354.             ((real) colors[index][0]) / 255.0, 
  4355.             ((real) colors[index][1]) / 255.0, 
  4356.             ((real) colors[index][2]) / 255.0);
  4357.         if (hsv[2] < 0.0) hsv[2] = 0.0;
  4358.         else if (hsv[2] > 1.0) hsv[2] = 1.0;
  4359.     }
  4360.     else
  4361.     {
  4362.         /*No value*/
  4363.         newValue = NULLOBJ;
  4364.     }
  4365.     changedValue = GetMethod(colorWheel, CHANGEDVALUE);
  4366.     SetMethod(colorWheel, CHANGEDVALUE, 0);
  4367.     newValue = NewRealArray(1, 2L);
  4368.     ((real *) ELEMENTS(newValue))[0] = hsv[0];
  4369.     ((real *) ELEMENTS(newValue))[1] = hsv[1];
  4370.     SetValue(colorWheel, newValue);
  4371.     SetMethod(colorWheel, CHANGEDVALUE, changedValue);
  4372.     }
  4373.     else
  4374.     {
  4375.     ActivateColorWheel(colorWheel, false);
  4376.     }
  4377.  
  4378.     buttons = GetVar(colorBar, FULLCOMPBUTTONS);
  4379.     if (buttons)
  4380.     {
  4381.     buttonList = LISTOF(buttons);
  4382.     }
  4383.     else
  4384.     {
  4385.     buttonList = 0;
  4386.     }
  4387.  
  4388.     if (elements[0] > 0.0)
  4389.     {
  4390.     /*Active Slider and buttons*/
  4391.     int index1, index2;
  4392.     int comp;
  4393.  
  4394.     changedValue = GetMethod(slider, CHANGEDVALUE);
  4395.     SetMethod(slider, CHANGEDVALUE, 0);
  4396.     ActivateSlider(slider, true);
  4397.  
  4398.     /*Get a value for the slider*/
  4399.     index1 = elements[1];
  4400.     index2 = elements[2];
  4401.     if (elements[0] == 1.0)
  4402.     {
  4403.         comp = 0;
  4404.     }
  4405.     else
  4406.     {
  4407.         comp = 5 - (int) elements[0];
  4408.     }
  4409.     ChoosePaletteSliderValue(slider, palette, comp,
  4410.         index1, index2);
  4411.     SetMethod(slider, CHANGEDVALUE, changedValue);
  4412.  
  4413.     /*Activate buttons*/
  4414.     while (buttonList)
  4415.     {
  4416.         ActivateButton(buttonList -> thing, true);
  4417.         buttonList = buttonList -> next;
  4418.     }
  4419.     }
  4420.     else
  4421.     {
  4422.     /*Inactive Slider*/
  4423.     ActivateSlider(slider, false);
  4424.  
  4425.     /*Deactivate buttons*/
  4426.     while (buttonList)
  4427.     {
  4428.         ActivateButton(buttonList -> thing, false);
  4429.         buttonList = buttonList -> next;
  4430.     }
  4431.     }
  4432.     buttons = GetVar(colorBar, COMPBUTTONS);
  4433.     if (buttons)
  4434.     {
  4435.     buttonList = LISTOF(buttons);
  4436.     }
  4437.     else
  4438.     {
  4439.     buttonList = 0;
  4440.     }
  4441.     if (elements[0] > 1.0 && elements[2] > elements[1])
  4442.     {
  4443.     /*Activate buttons*/
  4444.     while (buttonList)
  4445.     {
  4446.         ActivateButton(buttonList -> thing, true);
  4447.         buttonList = buttonList -> next;
  4448.     }
  4449.     }
  4450.     else
  4451.     {
  4452.     /*Deactivate buttons*/
  4453.     while (buttonList)
  4454.     {
  4455.         ActivateButton(buttonList -> thing, false);
  4456.         buttonList = buttonList -> next;
  4457.     }
  4458.     }
  4459.  
  4460.     button = GetVar(colorBar, FREEFORMBUTTON);
  4461.     if (elements[0] > 1.0)
  4462.     {
  4463.      if (button)
  4464.     {
  4465.         ActivateButton(button, true);
  4466.     }
  4467.     }
  4468.     else
  4469.     {
  4470.      if (button)
  4471.     {
  4472.         ActivateButton(button, false);
  4473.     }
  4474.     }
  4475.  
  4476.     ImInvalid(colorBar);
  4477.     return ObjTrue;
  4478. }
  4479.  
  4480. static ObjPtr ChangePaletteColorWheel(colorWheel)
  4481. ObjPtr colorWheel;
  4482. /*Changes a color wheel*/
  4483. {
  4484.     ObjPtr slider, colorBar, panel, button; 
  4485.     ObjPtr palette;
  4486.     ObjPtr var;
  4487.     real h, s, v;
  4488.     real r, g, b;
  4489.     int rs, gs, bs;
  4490.     short3 *colors;
  4491.     int index1, index2, k;
  4492.     real *elements;
  4493.  
  4494.     slider = GetObjectVar("ChangePaletteColorWheel", colorWheel, SLIDER);
  4495.     colorBar = GetObjectVar("ChangePaletteColorWheel", colorWheel, COLORBAR);
  4496.  
  4497.     if (!slider || !colorBar)
  4498.     {
  4499.     return ObjFalse;
  4500.     }
  4501.  
  4502.     palette = GetPaletteVar("ChangePaletteColorWheel", colorBar, REPOBJ);
  4503.     if (!palette)
  4504.     {
  4505.     return ObjFalse;
  4506.     }
  4507.  
  4508.     var = GetValue(colorBar);
  4509.     if (!var)
  4510.     {
  4511.     return ObjFalse;
  4512.     }
  4513.     if (((real *) ELEMENTS(var))[0] != 1.0)
  4514.     {
  4515.     return ObjFalse;
  4516.     }
  4517.     index1 = ((real *) ELEMENTS(var))[1];
  4518.     index2 = ((real *) ELEMENTS(var))[2];
  4519.  
  4520.     var = GetValue(colorWheel);
  4521.     if (!var)
  4522.     {
  4523.     return ObjFalse;
  4524.     }
  4525.  
  4526.     h = ((real *) ELEMENTS(var))[0];
  4527.     s = ((real *) ELEMENTS(var))[1];
  4528.     var = GetValue(slider);
  4529.     if (!var)
  4530.     {
  4531.     return ObjFalse;
  4532.     }
  4533.     v = GetReal(var);
  4534.  
  4535.     HSV2RGB(&r, &g, &b, h, s, v);
  4536.  
  4537.     /*Change the palette.  Tricky.*/
  4538.     rs = r * 255.0;
  4539.     gs = g * 255.0;
  4540.     bs = b * 255.0;
  4541.     if (rs > 255) rs = 255;
  4542.     else if (rs < 0) rs = 0;
  4543.     if (gs > 255) gs = 255;
  4544.     else if (gs < 0) gs = 0;
  4545.     if (bs > 255) rs = 255;
  4546.     else if (bs < 0) bs = 0;
  4547.  
  4548.     /*DIKEO DESTRUCTIVE change*/
  4549.     MakeVar(palette, COLORS);
  4550.     var = GetVar(palette, COLORS);
  4551.     if (!var) return ObjFalse;
  4552.     colors = ELEMENTS(var);
  4553.  
  4554.     for (k = index1; k <= index2; ++k)
  4555.     {
  4556.     colors[k][0] = rs;
  4557.     colors[k][1] = gs;
  4558.     colors[k][2] = bs;
  4559.     }
  4560.  
  4561.     CopyColorsToComponents(palette);
  4562.  
  4563. #ifdef GRAPHICS
  4564.     MapPaletteColors(palette, index1, index2);
  4565. #endif
  4566.  
  4567.  
  4568.     SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  4569.     panel = GetVar(colorWheel, PARENT);
  4570.     if (panel)
  4571.     {
  4572.     button = GetVar(panel, KEEPBUTTON);
  4573.     if (button)
  4574.     {
  4575.         ActivateButton(button, true);
  4576.     }
  4577.     button = GetVar(panel, REVERTBUTTON);
  4578.     if (button)
  4579.     {
  4580.         ActivateButton(button, true);
  4581.     }
  4582.     }
  4583.  
  4584.     SetVar(slider, TEMPPALETTE, CloneObject(palette));
  4585. /*    interactiveMoving = false;*/
  4586.     ForAllVisWindows(ImInvalid);
  4587.     DrawMe(colorBar);
  4588.     return ObjTrue;
  4589. }
  4590.  
  4591. static ObjPtr ChangePaletteSlider(slider)
  4592. ObjPtr slider;
  4593. /*Changes a palette's slider*/
  4594. {
  4595.     ObjPtr colorBar, panel, button; 
  4596.     ObjPtr palette, tempPalette;
  4597.     ObjPtr var;
  4598.     short rs, gs, bs;
  4599.     short3 *colors, *tempColors;
  4600.     int index1, index2, k, comp;
  4601.     real sliderValue, initValue;
  4602.     real change;
  4603.     ObjPtr radio;
  4604.     ObjPtr colorWheel, hsObj;
  4605.  
  4606.     colorBar = GetObjectVar("ChangePaletteSlider", slider, COLORBAR);
  4607.     tempPalette = GetPaletteVar("ChangePaletteSlider", slider, TEMPPALETTE);
  4608.  
  4609.     if (!colorBar || !tempPalette)
  4610.     {
  4611.     return ObjFalse;
  4612.     }
  4613.  
  4614.     palette = GetPaletteVar("ChangePaletteSlider", colorBar, REPOBJ);
  4615.     if (!palette)
  4616.     {
  4617.     return ObjFalse;
  4618.     }
  4619.  
  4620.     colorWheel = GetObjectVar("ChangePaletteSlider", colorBar, COLORWHEEL);
  4621.     if (!colorWheel)
  4622.     {
  4623.     return ObjFalse;
  4624.     }
  4625.  
  4626.     var = GetRealVar("ChangePaletteSlider", slider, INITVALUE);
  4627.     if (var)
  4628.     {
  4629.     initValue = GetReal(var);
  4630.     }
  4631.     else
  4632.     {
  4633.     return ObjFalse;
  4634.     }
  4635.  
  4636.     var = GetValue(colorBar);
  4637.     if (!var)
  4638.     {
  4639.     return ObjFalse;
  4640.     }
  4641.     
  4642.     comp = 5 - ((real *) ELEMENTS(var))[0];
  4643.     if (comp == 4) comp = 0;
  4644.     if (comp < 0)
  4645.     {
  4646.     return ObjFalse;
  4647.     }
  4648.     index1 = ((real *) ELEMENTS(var))[1];
  4649.     index2 = ((real *) ELEMENTS(var))[2];
  4650.  
  4651.     var = GetValue(slider);
  4652.     if (!var)
  4653.     {
  4654.     return ObjFalse;
  4655.     }
  4656.     sliderValue = GetReal(var);
  4657.  
  4658.     /*DIKEO DESTRUCTIVE*/
  4659.     MakeVar(palette, COLORS);
  4660.     var = GetVar(palette, COLORS);
  4661.     if (!var) return ObjFalse;
  4662.     colors = ELEMENTS(var);
  4663.  
  4664.     MakeVar(tempPalette, COLORS);
  4665.     var = GetVar(tempPalette, COLORS);
  4666.     if (!var) return ObjFalse;
  4667.     tempColors = ELEMENTS(var);
  4668.  
  4669.     if (sliderValue < initValue)
  4670.     {
  4671.     /*Attenuate value*/
  4672.     change = sliderValue / initValue;
  4673.  
  4674.     if (comp == 0)
  4675.     {
  4676.         /*Full color*/
  4677.         real h, s, v, dummy;
  4678.         real r, g, b;
  4679.  
  4680.         for (k = index1; k <= index2; ++k)
  4681.         {
  4682.         r = tempColors[k][0] / 255.0;
  4683.         g = tempColors[k][1] / 255.0;
  4684.         b = tempColors[k][2] / 255.0;
  4685.  
  4686.         RGB2HSV(&h, &s, &v, r, g, b);
  4687.         if (index1 == index2)
  4688.         {
  4689.             hsObj = GetValue(colorWheel);
  4690.             if (!hsObj || !IsRealArray(hsObj) || RANK(hsObj) != 1 || DIMS(hsObj)[0] != 2)
  4691.             {
  4692.             return ObjFalse;
  4693.             }
  4694.             /*Single color, refresh value from wheel*/
  4695.             h = ((real *) ELEMENTS(hsObj))[0];
  4696.             s = ((real *) ELEMENTS(hsObj))[1];
  4697.             v = sliderValue;
  4698.         }
  4699.         else
  4700.         {
  4701.             v *= change;
  4702.         }
  4703.         if (v > 1.0) v = 1.0;
  4704.         if (v < 0.0) v = 0.0;
  4705.         HSV2RGB(&r, &g, &b, h, s, v);
  4706.  
  4707.         rs = r * 255.0 + 0.5;
  4708.         gs = g * 255.0 + 0.5;
  4709.         bs = b * 255.0 + 0.5;
  4710.         colors[k][0] = rs;
  4711.         colors[k][1] = gs;
  4712.         colors[k][2] = bs;
  4713.         }
  4714.         CopyColorsToComponents(palette);
  4715.     }
  4716.     else
  4717.     {
  4718.         real component;
  4719.  
  4720.         for (k = index1; k <= index2; ++k)
  4721.         {
  4722.         component = ((real) GetColorComponent(tempPalette, k, comp - 1)) / 255.0;
  4723.         component *= change;
  4724.         if (component > 1.0) component = 1.0;
  4725.         else if (component < 0.0) component = 0.0;
  4726.             SetColorComponent(palette, k, comp - 1, (int) (component * 255.0 + 0.5));
  4727.         }
  4728.         CopyComponentsToColors(palette);
  4729.     }
  4730. #ifdef GRAPHICS
  4731.     MapPaletteColors(palette, index1, index2);
  4732. #endif
  4733.     }
  4734.     else
  4735.     {
  4736.     /*Brighten value*/
  4737.     change = (1.0 - sliderValue) / (1.0 - initValue);
  4738.     if (comp == 0)
  4739.     {
  4740.         /*Full color*/
  4741.         real h, s, v, dummy;
  4742.         real r, g, b;
  4743.  
  4744.         for (k = index1; k <= index2; ++k)
  4745.         {
  4746.         r = tempColors[k][0] / 255.0;
  4747.         g = tempColors[k][1] / 255.0;
  4748.         b = tempColors[k][2] / 255.0;
  4749.  
  4750.         RGB2HSV(&h, &s, &v, r, g, b);
  4751.         if (index1 == index2)
  4752.         {
  4753.             /*Single color, refresh value from wheel*/
  4754.             hsObj = GetValue(colorWheel);
  4755.             if (!hsObj || !IsRealArray(hsObj) || RANK(hsObj) != 1 || DIMS(hsObj)[0] != 2)
  4756.             {
  4757.             return ObjFalse;
  4758.             }
  4759.             h = ((real *) ELEMENTS(hsObj))[0];
  4760.             s = ((real *) ELEMENTS(hsObj))[1];
  4761.             v = sliderValue;
  4762.         }
  4763.         else
  4764.         {
  4765.             v = 1.0 - (1.0 - v) * change;
  4766.         }
  4767.         if (v > 1.0) v = 1.0;
  4768.         if (v < 0.0) v = 0.0;
  4769.         HSV2RGB(&r, &g, &b, h, s, v);
  4770.  
  4771.         rs = r * 255.0 + 0.5;
  4772.         gs = g * 255.0 + 0.5;
  4773.         bs = b * 255.0 + 0.5;
  4774.         colors[k][0] = rs;
  4775.         colors[k][1] = gs;
  4776.         colors[k][2] = bs;
  4777.         }
  4778.         CopyColorsToComponents(palette);
  4779.     }
  4780.     else
  4781.     {
  4782.         real component;
  4783.  
  4784.         for (k = index1; k <= index2; ++k)
  4785.         {
  4786.         component = ((real) GetColorComponent(tempPalette, k, comp - 1)) / 255.0;
  4787.         component = 1.0 - (1.0 - component) * change;
  4788.         if (component > 1.0) component = 1.0;
  4789.         else if (component < 0.0) component = 0.0;
  4790.             SetColorComponent(palette, k, comp - 1, (int) (component * 255.0 + 0.5));
  4791.         }
  4792.         CopyComponentsToColors(palette);
  4793.     }
  4794. #ifdef GRAPHICS
  4795.     MapPaletteColors(palette, index1, index2);
  4796. #endif
  4797.     }
  4798.  
  4799.     ResetColorBarTools(colorBar);
  4800.  
  4801.     SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  4802.     panel = GetVar(slider, PARENT);
  4803.     if (panel)
  4804.     {
  4805.     button = GetVar(panel, KEEPBUTTON);
  4806.     if (button)
  4807.     {
  4808.         ActivateButton(button, true);
  4809.     }
  4810.     button = GetVar(panel, REVERTBUTTON);
  4811.     if (button)
  4812.     {
  4813.         ActivateButton(button, true);
  4814.     }
  4815.     }
  4816.  
  4817. /*    interactiveMoving = false;*/
  4818.     ForAllVisWindows(ImInvalid);
  4819.     DrawMe(colorBar);
  4820.     return ObjTrue;
  4821. }
  4822.  
  4823.  
  4824. static ObjPtr RevertPalette(repObj)
  4825. ObjPtr repObj;
  4826. /*Reverts a palette in repObj*/
  4827. {
  4828.     ObjPtr keptPalette, colorBar;
  4829.  
  4830.     keptPalette = GetPaletteVar("RevertPalette", repObj, KEPTPALETTE);
  4831.     if (!keptPalette)
  4832.     {
  4833.     return;
  4834.     }
  4835.     CopyPalette(repObj, keptPalette);
  4836.     SetVar(repObj, CHANGED, ObjTrue);
  4837.  
  4838.     if (colorBar = GetObjectVar("RevertPalette", repObj, COLORBAR))
  4839.     {
  4840.     ObjPtr var;
  4841.     real newValue[3];
  4842.  
  4843.     InhibitLogging(true);
  4844.     newValue[0] = newValue[1] = newValue[2] = 0.0;
  4845.     var = NewRealArray(1, 3L);
  4846.     CArray2Array(var, newValue);
  4847.     SetValue(colorBar, var);
  4848.     InhibitLogging(false);
  4849.     }
  4850.  
  4851.     /*DIKEO figure out a better way of doing this*/
  4852.     ForAllVisWindows(ImInvalid);
  4853.  
  4854.     return ObjTrue;
  4855. }
  4856.  
  4857. static ObjPtr KeepPalette(palette)
  4858. ObjPtr palette;
  4859. /*Keeps the changes in the palette*/
  4860. {
  4861.     ObjPtr keptPalette;
  4862.  
  4863.     keptPalette = GetVar(palette, KEPTPALETTE);
  4864.     CopyPalette(keptPalette, palette);
  4865.     SetVar(palette, KEPTPALETTE, keptPalette);
  4866.  
  4867.     return ObjTrue;
  4868. }
  4869.  
  4870. #ifdef PROTO
  4871. static void SimplePaletteFunction(int whichFunc, ObjPtr palette,
  4872.     int index1, int index2, int comp, ObjPtr colorBar)
  4873. #else
  4874. static void SimplePaletteFunction(whichFunc, palette, index1, index2, comp, colorBar)
  4875. int whichFunc;
  4876. ObjPtr palette;
  4877. int index1, index2, comp;
  4878. ObjPtr colorBar;
  4879. #endif
  4880. /*Does a simple function on palette*/
  4881. {
  4882.     int k;
  4883.     real r1, g1, b1, r2, g2, b2, r3, g3, b3, r, g, b, c;
  4884.     int rs, gs, bs, cs;
  4885.     ObjPtr var;
  4886.     real *minmax;
  4887.     int nColors;
  4888.  
  4889.     var = GetVar(palette, MINMAX);
  4890.     if (!var)
  4891.     {
  4892.     return;
  4893.     }
  4894.     minmax = ELEMENTS(var);
  4895.  
  4896.     var = GetIntVar("SimplePaletteFunction", palette, NCOLORS);
  4897.     if (!var) return;
  4898.     nColors = GetInt(var);
  4899.  
  4900.     if (logging)
  4901.     {
  4902.     Log("effect ");
  4903.     Log(spfNames[whichFunc]);
  4904.     Log("\n");
  4905.     }
  4906.  
  4907.     switch (whichFunc)
  4908.     {
  4909.     case PF_RAMP:
  4910.         /*Change the palette to a ramp*/
  4911.         for (k = index1 + 1; k < index2; ++k)
  4912.         {
  4913.         if (comp == 0 || comp == 1)
  4914.         {
  4915.             c = ((k - index1) * (GetColorComponent(palette, index2, 0) / 255.0)
  4916.                + (index2 - k) * (GetColorComponent(palette, index1, 0) / 255.0)) / (index2 - index1);
  4917.     
  4918.             cs = c * 255.0;
  4919.  
  4920.             SetColorComponent(palette, k, 0, cs);
  4921.         }
  4922.         if (comp == 0 || comp == 2)
  4923.         {
  4924.             c = ((k - index1) * (GetColorComponent(palette, index2, 1) / 255.0)
  4925.                + (index2 - k) * (GetColorComponent(palette, index1, 1) / 255.0)) / (index2 - index1);
  4926.     
  4927.             cs = c * 255.0;
  4928.  
  4929.             SetColorComponent(palette, k, 1, cs);
  4930.         }
  4931.         if (comp == 0 || comp == 3)
  4932.         {
  4933.             c = ((k - index1) * (GetColorComponent(palette, index2, 2) / 255.0)
  4934.                + (index2 - k) * (GetColorComponent(palette, index1, 2) / 255.0)) / (index2 - index1);
  4935.     
  4936.             cs = c * 255.0;
  4937.  
  4938.             SetColorComponent(palette, k, 2, cs);
  4939.         }
  4940.         }
  4941.         break;
  4942.     case PF_REVERSE:
  4943.         for (k = 0; k < (index2 - index1 + 1) / 2; ++k)
  4944.         {
  4945.         int tempColor;
  4946.  
  4947.         if (comp == 0 || comp == 1)
  4948.         {
  4949.             /*First component*/
  4950.             tempColor = GetColorComponent(palette, index2 - k, 0);
  4951.             SetColorComponent(palette, index2 - k, 0, 
  4952.             GetColorComponent(palette, index1 + k, 0));
  4953.             SetColorComponent(palette, index1 + k, 0, tempColor);
  4954.         }
  4955.  
  4956.         if (comp == 0 || comp == 2)
  4957.         {
  4958.             /*Secpmd component*/
  4959.             tempColor = GetColorComponent(palette, index2 - k, 1);
  4960.             SetColorComponent(palette, index2 - k, 1, 
  4961.             GetColorComponent(palette, index1 + k, 1));
  4962.             SetColorComponent(palette, index1 + k, 1, tempColor);
  4963.         }
  4964.  
  4965.         if (comp == 0 || comp == 3)
  4966.         {
  4967.             /*Third component*/
  4968.             tempColor = GetColorComponent(palette, index2 - k, 2);
  4969.             SetColorComponent(palette, index2 - k, 2, 
  4970.             GetColorComponent(palette, index1 + k, 2));
  4971.             SetColorComponent(palette, index1 + k, 2, tempColor);
  4972.         }
  4973.         }
  4974.         break;
  4975.     case PF_RUFFLE:
  4976.         {
  4977.         int left, right, bottom, top, l, r;
  4978.         long oldQuotient, newQuotient;
  4979.         double ddiff, majorWidth, minorWidth, halfSpace;
  4980.         real val;
  4981.         ObjPtr var;
  4982.         int nTics;
  4983.  
  4984.         Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
  4985.  
  4986.         l = left + CBLBORDER + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
  4987.         r = right  - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
  4988.         halfSpace = (minmax[1] - minmax[0]) / (nColors - 4) * 0.5;
  4989.         ddiff = minmax[1] - minmax[0] + 2 * halfSpace;
  4990.         CalcGoodSteps(ddiff,
  4991.             r - l,
  4992.             CBSTEPPIXELS,
  4993.             &majorWidth, &nTics);
  4994.  
  4995.         minorWidth = majorWidth / nTics;
  4996.  
  4997.         l = index1;
  4998.         val = (l - 2) * ddiff / (nColors - 3);
  4999.         oldQuotient = val / minorWidth;
  5000.         for (r = l + 1; r <= index2; ++r)
  5001.         {
  5002.             val = (r - 2) * ddiff / (nColors - 3);
  5003.             newQuotient = val / minorWidth;
  5004.             if (newQuotient != oldQuotient ||
  5005.             r == index2)
  5006.             {
  5007.             /*Time for a reversal*/
  5008.             if (r == index2) ++r;
  5009.             oldQuotient = newQuotient;
  5010.                 for (k = 0; k < (r - l) / 2; ++k)
  5011.             {
  5012.                 int tempColor;
  5013.  
  5014.                 if (comp == 0 || comp == 1)
  5015.                 {
  5016.                 /*Component*/
  5017.                 tempColor = GetColorComponent(palette, r - 1 - k, 0);
  5018.                 SetColorComponent(palette, r - 1 - k, 0,
  5019.                     GetColorComponent(palette, l + k, 0));
  5020.                 SetColorComponent(palette, l + k, 0, tempColor);
  5021.                 }
  5022.  
  5023.                 if (comp == 0 || comp == 2)
  5024.                 {
  5025.                 /*Component*/
  5026.                 tempColor = GetColorComponent(palette, r - 1 - k, 1);
  5027.                 SetColorComponent(palette, r - 1 - k, 1,
  5028.                     GetColorComponent(palette, l + k, 1));
  5029.                 SetColorComponent(palette, l + k, 1, tempColor);
  5030.                 }
  5031.  
  5032.                 if (comp == 0 || comp == 3)
  5033.                 {
  5034.                 /*Component*/
  5035.                 tempColor = GetColorComponent(palette, r - 1 - k, 2);
  5036.                 SetColorComponent(palette, r - 1 - k, 2,
  5037.                     GetColorComponent(palette, l + k, 2));
  5038.                 SetColorComponent(palette, l + k, 2, tempColor);
  5039.                 }
  5040.             }
  5041.             l = r;
  5042.             } 
  5043.         }
  5044.         }
  5045.         break;
  5046.     case PF_SMOOTH:
  5047.         if (index2 <= index1) break;
  5048.         r1 = (GetColorComponent(palette, index1, 0) + 0.5) / 255.0;
  5049.         g1 = (GetColorComponent(palette, index1, 1) + 0.5) / 255.0;
  5050.         b1 = (GetColorComponent(palette, index1, 2) + 0.5) / 255.0;
  5051.         r2 = (GetColorComponent(palette, index1 + 1, 0) + 0.5) / 255.0;
  5052.         g2 = (GetColorComponent(palette, index1 + 1, 1) + 0.5) / 255.0;
  5053.         b2 = (GetColorComponent(palette, index1 + 1, 2) + 0.5) / 255.0;
  5054.         for (k = index1 + 2; k < index2; ++k)
  5055.         {
  5056.         r3 = (GetColorComponent(palette, k + 1, 0) + 0.5) / 255.0;
  5057.         g3 = (GetColorComponent(palette, k + 1, 1) + 0.5) / 255.0;
  5058.         b3 = (GetColorComponent(palette, k + 1, 2) + 0.5) / 255.0;
  5059.  
  5060.         r = ((r1 + r3) * 0.5 + r2) * 0.5;
  5061.         g = ((g1 + g3) * 0.5 + g2) * 0.5;
  5062.         b = ((b1 + b3) * 0.5 + b2) * 0.5;
  5063.  
  5064.         rs = r * 255.0;
  5065.         gs = g * 255.0;
  5066.         bs = b * 255.0;
  5067.  
  5068.         if (comp == 0 || comp == 1)
  5069.         {
  5070.             SetColorComponent(palette, k, 0, rs);
  5071.         }
  5072.         if (comp == 0 || comp == 2)
  5073.         {
  5074.             SetColorComponent(palette, k, 1, gs);
  5075.         }
  5076.         if (comp == 0 || comp == 3)
  5077.         {
  5078.             SetColorComponent(palette, k, 2, bs);
  5079.         }
  5080.         r1 = r2; r2 = r3;
  5081.         g1 = g2; g2 = g3;
  5082.         b1 = b2; b2 = b3;
  5083.         }
  5084.         break;
  5085.     case PF_SHARPEN:
  5086.         if (index2 <= index1) break;
  5087.         r1 = (GetColorComponent(palette, index1, 0) + 0.5) / 255.0;
  5088.         g1 = (GetColorComponent(palette, index1, 1) + 0.5) / 255.0;
  5089.         b1 = (GetColorComponent(palette, index1, 2) + 0.5) / 255.0;
  5090.         r2 = (GetColorComponent(palette, index1 + 1, 0) + 0.5) / 255.0;
  5091.         g2 = (GetColorComponent(palette, index1 + 1, 1) + 0.5) / 255.0;
  5092.         b2 = (GetColorComponent(palette, index1 + 1, 2) + 0.5) / 255.0;
  5093.         for (k = index1 + 2; k < index2; ++k)
  5094.         {
  5095.         r3 = (GetColorComponent(palette, k + 1, 0) + 0.5) / 255.0;
  5096.         g3 = (GetColorComponent(palette, k + 1, 1) + 0.5) / 255.0;
  5097.         b3 = (GetColorComponent(palette, k + 1, 2) + 0.5) / 255.0;
  5098.  
  5099.         r = r2 + (r2 - (r1 + r3) * 0.5) * 2.0;
  5100.         if (r > 1.0) r = 1.0; else if (r < 0.0) r = 0.0;
  5101.         g = g2 + (g2 - (g1 + g3) * 0.5) * 2.0;
  5102.         if (g > 1.0) g = 1.0; else if (g < 0.0) g = 0.0;
  5103.         b = b2 + (b2 - (b1 + b3) * 0.5) * 2.0;
  5104.         if (b > 1.0) b = 1.0; else if (b < 0.0) b = 0.0;
  5105.  
  5106.         rs = r * 255.0;
  5107.         gs = g * 255.0;
  5108.         bs = b * 255.0;
  5109.  
  5110.         if (comp == 0 || comp == 1)
  5111.         {
  5112.             SetColorComponent(palette, k, 0, rs);
  5113.         }
  5114.         if (comp == 0 || comp == 2)
  5115.         {
  5116.             SetColorComponent(palette, k, 1, gs);
  5117.         }
  5118.         if (comp == 0 || comp == 3)
  5119.         {
  5120.             SetColorComponent(palette, k, 2, bs);
  5121.         }
  5122.         r1 = r2; r2 = r3;
  5123.         g1 = g2; g2 = g3;
  5124.         b1 = b2; b2 = b3;
  5125.         }
  5126.         break;
  5127.     }
  5128.     CopyComponentsToColors(palette);
  5129. }
  5130.  
  5131. static ObjPtr SimpleFuncButton(button)
  5132. ObjPtr button;
  5133. /*Do a simple palette function*/
  5134. {
  5135.     ObjPtr colorBar, panel; 
  5136.     ObjPtr palette;
  5137.     ObjPtr var;
  5138.     int whichFunc;
  5139.     int index1, index2, comp, k;
  5140.  
  5141.     colorBar = GetObjectVar("SimpleFuncButton", button, COLORBAR);
  5142.     if (!colorBar)
  5143.     {
  5144.     return ObjFalse;
  5145.     }
  5146.  
  5147.     var = GetIntVar("SimpleFuncButton", button, PALETTEFUNC);
  5148.     if (!var)
  5149.     {
  5150.     return ObjFalse;
  5151.     }
  5152.     whichFunc = GetInt(var);
  5153.  
  5154.     palette = GetPaletteVar("SimpleFuncButton", colorBar, REPOBJ);
  5155.     if (!palette)
  5156.     {
  5157.     return false;
  5158.     }
  5159.  
  5160.     var = GetValue(colorBar);
  5161.     if (!var)
  5162.     {
  5163.     return ObjFalse;
  5164.     }
  5165.     if (((real *) ELEMENTS(var))[0] < 1.0)
  5166.     {
  5167.     return ObjFalse;
  5168.     }
  5169.     index1 = ((real *) ELEMENTS(var))[1];
  5170.     index2 = ((real *) ELEMENTS(var))[2];
  5171.  
  5172.     if (((real *) ELEMENTS(var))[0] == 1.0)
  5173.     {
  5174.     comp = 0;
  5175.     }
  5176.     else
  5177.     {
  5178.     comp = 5 - (int) ((real *) ELEMENTS(var))[0];
  5179.     }
  5180.  
  5181.     SimplePaletteFunction(whichFunc, palette, index1, index2, comp, colorBar);
  5182.  
  5183. #ifdef GRAPHICS
  5184.     MapPaletteColors(palette, index1, index2);
  5185. #endif
  5186.  
  5187.     SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  5188.     panel = GetVar(button, PARENT);
  5189.     if (panel)
  5190.     {
  5191.     button = GetVar(panel, KEEPBUTTON);
  5192.     if (button)
  5193.     {
  5194.         ActivateButton(button, true);
  5195.     }
  5196.     button = GetVar(panel, REVERTBUTTON);
  5197.     if (button)
  5198.     {
  5199.         ActivateButton(button, true);
  5200.     }
  5201.     }
  5202.  
  5203. /*   interactiveMoving = false;*/
  5204.     InhibitLogging(true);
  5205.     ChangedValue(colorBar);
  5206.     InhibitLogging(false);
  5207. /*DIKEO figure out a better way of doing this*/
  5208.     ForAllVisWindows(ImInvalid);
  5209.     ImInvalid(colorBar);
  5210.     return ObjTrue;
  5211. }
  5212.  
  5213. #ifdef PROTO
  5214. void ActivateColorWheel(ObjPtr wheel, Bool whether)
  5215. #else
  5216. void ActivateColorWheel(wheel, whether)
  5217. ObjPtr wheel;
  5218. Bool whether;
  5219. #endif
  5220. /*Activates a color wheel*/
  5221. {
  5222.     SetVar(wheel, ACTIVATED, whether ? ObjTrue : ObjFalse);
  5223.     ImInvalid(wheel);
  5224. }
  5225.  
  5226. #ifdef PROTO
  5227. static int GetColorComponent(ObjPtr palette, int whichColor, int comp)
  5228. #else
  5229. static int GetColorComponent(palette, whichColor, comp)
  5230. ObjPtr palette;
  5231. int whichColor;
  5232. int comp;
  5233. #endif
  5234. /*Gets the color component comp from whichColor in palette*/
  5235. {
  5236.     ObjPtr var;
  5237.     short3 *components;
  5238.  
  5239.     var = GetVar(palette, COLORCOMP);
  5240.     components = ELEMENTS(var);
  5241.     return components[whichColor][comp];
  5242. }
  5243.  
  5244. #ifdef PROTO
  5245. static void SetColorComponent(ObjPtr palette, int whichColor, int comp, int cc)
  5246. #else
  5247. static void SetColorComponent(palette, whichColor, comp, cc)
  5248. ObjPtr palette, int whichColor; int comp; int cc;
  5249. #endif
  5250. /*Changes component comp in whichColor of palette to cc*/
  5251. {
  5252.     real rgb[3], hsv[3], hls[3], yiq[3];
  5253.     ObjPtr var;
  5254.     short3 *components;
  5255.  
  5256.     var = GetVar(palette, COLORCOMP);
  5257.     components = ELEMENTS(var);
  5258.  
  5259.     /*DIKEO DESTRUCTIVE*/
  5260.     components[whichColor][comp] = cc;
  5261. }
  5262.  
  5263. #ifdef PROTO
  5264. ObjPtr ImposeColorFunction(ObjPtr colorBar)
  5265. #else
  5266. ObjPtr ImposeColorFunction(colorBar)
  5267. ObjPtr colorBar;
  5268. #endif
  5269. /*Imposes a color function on colorBar.
  5270.   Function is given by EDITMODE
  5271.   Box is given by FUNCTIONBOX
  5272. */
  5273. {
  5274.     ObjPtr value, var, palette, panel, button;
  5275.     real *elements;
  5276.     int comp;
  5277.     int index1, index2, k, cc;
  5278.     real beg, end, fieldVal;
  5279.     int min, max;
  5280.     int tool;
  5281.     int cm;
  5282.  
  5283.     value = GetValue(colorBar);
  5284.     if (!value)
  5285.     {
  5286.     return ObjFalse;
  5287.     }
  5288.  
  5289.     palette = GetPaletteVar("ImposeColorFunction", colorBar, REPOBJ);
  5290.     if (!palette)
  5291.     {
  5292.     return ObjFalse;
  5293.     }
  5294.  
  5295.     elements = ELEMENTS(value);
  5296.     if (elements[1] < 1.5)
  5297.     {
  5298.     /*Not on a component*/
  5299.     return ObjFalse;
  5300.     }
  5301.  
  5302.     var = GetIntVar("ImposeColorFunction", colorBar, EDITMODE);
  5303.     if (!var)
  5304.     {
  5305.     return ObjFalse;
  5306.     }
  5307.     tool = GetInt(var);
  5308.  
  5309.     comp = 4 - elements[0];
  5310.  
  5311.     index1 = elements[1] + 0.5;
  5312.     index2 = elements[2] + 0.5;
  5313.  
  5314.     var = GetVar(colorBar, FUNCTIONBOX);
  5315.     if (!var)
  5316.     {
  5317.     /*No box around function!*/
  5318.     return ObjFalse;
  5319.     }
  5320.  
  5321.     elements = ELEMENTS(var);
  5322.     beg = elements[0];
  5323.     end = elements[1];
  5324.     min = elements[2] + 0.5;
  5325.     max = elements[3] + 0.5;
  5326.  
  5327.     var = GetVar(palette, COLORMODEL);
  5328.     if (var)
  5329.     {
  5330.     cm = GetInt(var);
  5331.     }
  5332.     else
  5333.     {
  5334.     cm = CM_RGB;
  5335.     }
  5336.  
  5337.     for (k = index1; k <= index2; ++k)
  5338.     {
  5339.     fieldVal = GetColorValue(palette, k);
  5340.     while (fieldVal < beg)
  5341.     {
  5342.         fieldVal += end - beg;
  5343.     }
  5344.     while (fieldVal > end)
  5345.     {
  5346.         fieldVal -= end - beg;
  5347.     }
  5348.     fieldVal -= beg;
  5349.     fieldVal /= (end - beg);
  5350.     /*Now fieldVal is in [0, 1) */
  5351.  
  5352.     switch (tool)
  5353.     {
  5354.         case PT_SINE:        /*Sine function*/
  5355.         cc = min + (max - min) * ((1.0 + rsin(fieldVal * 2.0 * M_PI)) * 0.5);
  5356.         break;
  5357.         case PT_TRIANGLE:        /*Triangle function*/
  5358.         if (fieldVal < 0.25)
  5359.         {
  5360.             cc = (max + min) / 2 + fieldVal * 2.0 * (max - min);
  5361.         }
  5362.         else if (fieldVal > 0.75)
  5363.         {
  5364.             cc = min + (fieldVal - 0.75) * 2.0 * (max - min);
  5365.         }
  5366.         else
  5367.         {
  5368.             cc = min + (0.75 - fieldVal) * 2.0 * (max - min);
  5369.         }
  5370.         break;
  5371.         case PT_SAWTOOTH:        /*Sawtooth function*/
  5372.         cc = min + fieldVal * (max - min);
  5373.         break;
  5374.         case PT_TOOTHSAW:        /*Toothsaw function*/
  5375.         cc = max - fieldVal * (max - min);
  5376.         break;
  5377.         case PT_SQUARE:        /*Square wave function*/
  5378.         if (fieldVal < 0.5)
  5379.         {
  5380.             cc = max;
  5381.         }
  5382.         else
  5383.         {
  5384.             cc = min;
  5385.         }
  5386.         break;
  5387.         default:
  5388.         cc = 0;
  5389.     }
  5390.     SetColorComponent(palette, k, comp, cc);
  5391.     }
  5392.     CopyComponentsToColors(palette);
  5393.  
  5394.     MapPaletteColors(palette, index1, index2);
  5395.  
  5396.     panel = GetVar(colorBar, PARENT);
  5397.     if (panel)
  5398.     {
  5399.     button = GetVar(panel, KEEPBUTTON);
  5400.     if (button)
  5401.     {
  5402.         ActivateButton(button, true);
  5403.     }
  5404.     button = GetVar(panel, REVERTBUTTON);
  5405.     if (button)
  5406.     {
  5407.         ActivateButton(button, true);
  5408.     }
  5409.     }
  5410.     SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  5411.  
  5412.     return ObjTrue;
  5413. }
  5414.  
  5415. static ObjPtr ChangeColorTool(group)
  5416. ObjPtr group;
  5417. /*Changes a color tool in response to a radio button group*/
  5418. {
  5419.     ObjPtr colorBar;
  5420.     ObjPtr palette;
  5421.     ObjPtr value;
  5422.     ObjPtr var;
  5423.     int tool;
  5424.     ObjPtr selection;
  5425.     real *elements;
  5426.     int nColors;
  5427.  
  5428.     colorBar = GetObjectVar("ChangeColorTool", group, REPOBJ);
  5429.     if (!colorBar)
  5430.     {
  5431.     return ObjFalse;
  5432.     }
  5433.  
  5434.     selection = GetValue(colorBar);
  5435.     elements = ELEMENTS(selection);
  5436.  
  5437.     palette = GetPaletteVar("ChangeColorTool", colorBar, REPOBJ);
  5438.     if (!palette)
  5439.     {
  5440.     return ObjFalse;
  5441.     }
  5442.  
  5443.     var = GetIntVar("ChangeColorTool", palette, NCOLORS);
  5444.     if (!var)
  5445.     {
  5446.     return ObjFalse;
  5447.     }
  5448.     nColors = GetInt(var);
  5449.  
  5450.     value = GetValue(group);
  5451.     if (!value)
  5452.     {
  5453.     return false;
  5454.     }
  5455.     tool = GetInt(value);
  5456.  
  5457.     var = GetVar(colorBar, EDITMODE);
  5458.     if (var && GetInt(var) == tool)
  5459.     {
  5460.     /*Don't need to do anything*/
  5461.     return ObjFalse;
  5462.     }
  5463.  
  5464.     SetVar(colorBar, EDITMODE, NewInt(tool));
  5465.  
  5466.     if (tool > 0)
  5467.     {
  5468.     /*It's a function.*/
  5469.     var = GetVar(colorBar, FUNCTIONBOX);
  5470.     if (!var)
  5471.     {
  5472.         /*Calculate initial function box*/
  5473.         int left, right, bottom, top, l, r, b, t;
  5474.         double majorWidth;
  5475.         double halfSpace;
  5476.         double start, finish, middle, ddiff;
  5477.         int nTics;
  5478.         long temp;
  5479.         real *minmax;
  5480.  
  5481.         var = GetFixedArrayVar("ChangeColorTool", palette, MINMAX, 1, 2L);
  5482.         if (!var)
  5483.         {
  5484.         return ObjFalse;
  5485.         }
  5486.         minmax = ELEMENTS(var);
  5487.  
  5488.         Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
  5489.  
  5490.         l = left + CBLBORDER + 1;
  5491.         r = right - CBRBORDER - 1;
  5492.  
  5493.         halfSpace = (minmax[1] - minmax[0]) / (nColors - 4) * 0.5;
  5494.         start = GetColorValue(palette, (int) elements[1]) - halfSpace;
  5495.         finish = GetColorValue(palette, (int) elements[2]) + halfSpace;
  5496.         middle = (start + finish) * 0.5;
  5497.         ddiff = finish - start;
  5498.  
  5499.         CalcGoodSteps(ddiff,
  5500.               r - l,
  5501.               CBSTEPPIXELS,
  5502.               &majorWidth, &nTics);
  5503.  
  5504.  
  5505.         /*Minor and major tics first*/
  5506.         temp = middle / majorWidth;
  5507.         start = temp * majorWidth;
  5508.         finish = start + majorWidth;
  5509.  
  5510.         var = NewRealArray(1, 4L);
  5511.         ((real *) ELEMENTS(var))[0] = start - majorWidth;
  5512.         ((real *) ELEMENTS(var))[1] = finish;
  5513.         ((real *) ELEMENTS(var))[2] = 0.0;
  5514.         ((real *) ELEMENTS(var))[3] = 255.0;
  5515.  
  5516.         InhibitLogging(true);
  5517.         SetFunctionBox(colorBar, var);
  5518.         InhibitLogging(false);
  5519.     }
  5520.     InhibitLogging(true);
  5521.     ImposeColorFunction(colorBar);
  5522.     SetVar(palette, JUSTCOLORCHANGE, ObjTrue);
  5523.     ForAllVisWindows(ImInvalid);
  5524.     InhibitLogging(false);
  5525.     }
  5526.     else
  5527.     {
  5528.     /*No function box*/
  5529.     InhibitLogging(true);
  5530.     SetFunctionBox(colorBar, NULLOBJ);
  5531.     InhibitLogging(false);
  5532.     }
  5533.  
  5534.     ImInvalid(colorBar);
  5535.     return ObjTrue;
  5536. }
  5537.  
  5538. static ObjPtr MakePaletteBarHelp(colorBar, class)
  5539. ObjPtr colorBar;
  5540. ObjPtr class;
  5541. /*Makes help for a color bar*/
  5542. {
  5543.     ObjPtr help, temp;
  5544.     ObjPtr var;
  5545.     int editMode;
  5546.     real *elements;
  5547.  
  5548.     help = NewString("This control shows a color palette.  The color bar at \
  5549. the bottom shows the range of colors in the palette associated with the field \
  5550. values, plus colors for missing data, overflow, and underflow values.  \
  5551. Above the color bar are three bars showing the magnitude of the three components \
  5552. of each color, plus a magnified readout at the top.\n\
  5553. \n\
  5554. You can select a range of colors to edit by clicking in the color bar or one of the \
  5555. three component bars and dragging through the colors you want to edit.  When you \
  5556. select a range, controls in the window that can edit the color will become active.  \
  5557. Also, the selected range will be expanded to fill the magnified readout at the top of the control.  \
  5558. When a color component is selected, you can edit it using the Edit Component \
  5559. buttons to the left.");
  5560.  
  5561.     var = GetValue(colorBar);
  5562.     if (var)
  5563.     {
  5564.     elements = ELEMENTS(var);
  5565.  
  5566.     if (elements[0] > 1.5)
  5567.     {
  5568.         /*A component is selected*/
  5569.         var = GetIntVar("MakePaletteBarHelp", colorBar, EDITMODE);
  5570.         if (var)
  5571.         {
  5572.         ObjPtr palette;
  5573.         int cm;
  5574.         editMode = GetInt(var);
  5575.  
  5576.         palette = GetVar(colorBar, REPOBJ);
  5577.         if (!palette)
  5578.         {
  5579.             return ObjFalse;
  5580.         }
  5581.  
  5582.         var = GetVar(palette, COLORMODEL);
  5583.         if (var)
  5584.         {
  5585.             cm = GetInt(var);
  5586.         }
  5587.         else
  5588.         {
  5589.             cm = CM_RGB;
  5590.         }
  5591.  
  5592.         sprintf(tempStr, "\n\nThe %s components of a range of colors are \
  5593. currently selected.  The Intensity slider on the left lets you change the brightness \
  5594. of this component of the range.  The buttons at the top of the window let you \
  5595. perform some simple functions over the entire range of colors.  Use Help In \
  5596. Context to find out what each of these buttons does.\n\n",
  5597.         componentNames[cm][4 - (int) (elements[0] + 0.5)]);
  5598.         temp = NewString(tempStr);
  5599.         help = ConcatStrings(help, temp);
  5600.  
  5601.         if (editMode == PT_FREEFORM)
  5602.         {
  5603.             /*Free form tool*/
  5604.             temp = NewString("The free form tool is selected.  \
  5605. You can modify the waveform shown at the top of the control by clicking and drawing \
  5606. within the box.  The Shift key will constrain motion in just the vertical or \
  5607. horizontal direction.\n");
  5608.             help = ConcatStrings(help, temp);
  5609.         }
  5610.         else
  5611.         {
  5612.             /*Waveform tool*/
  5613.             sprintf(tempStr, "The %s tool is selected.  Notice \
  5614. that there is a yellow box within the magnified readout at \
  5615. the top of the control.  This box encloses one period of a %s which is used \
  5616. to fill the entire selected range of the component.  ",
  5617.             toolNames[editMode], toolNames[editMode]);
  5618.             temp = NewString(tempStr);
  5619.             help = ConcatStrings(help, temp);
  5620.             temp = NewString("Click and drag the square \
  5621. handles on the top or bottom to change the minimum and maximum values of the wave.  Click \
  5622. Click and drag the handles on the left or right to change the beginning and end \
  5623. of the wave as well as its wavelength.  The Shift key will constrain motion to \
  5624. the nearest tic mark.  Click and drag within the box to move the entire waveform \
  5625. left or right.");
  5626.             help = ConcatStrings(help, temp);
  5627.         }
  5628.         }
  5629.     }
  5630.     else if (elements[0] > 0.5)
  5631.     {
  5632.         temp = NewString("\n\nA range of colors is \
  5633. currently selected.  The Intensity slider on the left lets you change the brightness \
  5634. of this component of the range.  The Color color wheel lets you change \
  5635. the hue and saturation of the entire range.  When you click on this \
  5636. control, the entire range will become a single color.  \
  5637. The buttons at the top of the window let you \
  5638. perform some simple functions over the entire range of colors.  Use Help In \
  5639. Context to find out what each of these buttons does.");
  5640.         help = ConcatStrings(help, temp);
  5641.     }
  5642.     }
  5643.  
  5644.     SetVar(class, HELPSTRING, help);
  5645.     return ObjTrue;
  5646. }
  5647.  
  5648. static ObjPtr ShowPaletteDisplayControls(display, windowName)
  5649. ObjPtr display;
  5650. char *windowName;
  5651. /*Makes a new control window to control a palette display*/
  5652. {
  5653.     WinInfoPtr controlWindow;
  5654.     ObjPtr var;
  5655.     ObjPtr panel;
  5656.     ObjPtr corral;
  5657.     ObjPtr contents;
  5658.     WinInfoPtr dialogExists;
  5659.     Bool hasBackground;
  5660.  
  5661.     dialogExists = DialogExists((WinInfoPtr) display, NewString("Controls"));
  5662.     controlWindow = GetDialog((WinInfoPtr) display, NewString("Controls"), windowName, 
  5663.     DSPPALWINWIDTH, DSPPALWINHEIGHT, DSPPALWINWIDTH,
  5664.     DSPPALWINHEIGHT, WINUI + WINFIXEDSIZE);
  5665.     
  5666.     if (!dialogExists)
  5667.     {
  5668.     long info;
  5669.     ObjPtr value;
  5670.     
  5671.     ObjPtr checkBox, icon, name, colorBar, titleBox, textBox, button;
  5672.     ObjPtr colorWheel, slider, radioGroup;
  5673.     int left, right, bottom, top;
  5674.  
  5675.     SetVar((ObjPtr) controlWindow, REPOBJ, display);
  5676.  
  5677.     /*Set help string*/
  5678.     SetVar((ObjPtr) controlWindow, HELPSTRING, NewString("This window \
  5679. shows controls for a color palette legend.  For information about any of the controls \
  5680. in the window, use Help In Context on the control.\n"));
  5681.  
  5682.     /*Add in a panel*/
  5683.     panel = NewPanel(greyPanelClass, 0, DSPPALWINWIDTH, 0, DSPPALWINHEIGHT);
  5684.  
  5685.     if (!panel)
  5686.     {
  5687.         return ObjFalse;
  5688.     }
  5689.     contents = GetVar((ObjPtr) controlWindow, CONTENTS);
  5690.     PrefixList(contents, panel);
  5691.     SetVar(panel, PARENT, (ObjPtr) controlWindow);
  5692.  
  5693.     contents = GetVar(panel, CONTENTS);
  5694.  
  5695.     /*Add in the group of controls for text color*/
  5696.     left = MAJORBORDER;
  5697.     top = DSPPALWINHEIGHT - MAJORBORDER;
  5698.     right = left + 4 * MAJORBORDER + COLORWHEELWIDTH + SLIDERWIDTH;
  5699.     
  5700.     titleBox = NewTitleBox(left, right,
  5701.             top - TITLEBOXTOP - MAJORBORDER - 2 * MINORBORDER - COLORWHEELWIDTH - CHECKBOXHEIGHT - TEXTBOXHEIGHT - TEXTBOXSEP,
  5702.             top, "Text and Lines");
  5703.     SetVar(titleBox, PARENT, panel);
  5704.     PrefixList(contents, titleBox);
  5705.     left += MAJORBORDER;
  5706.     right -= MAJORBORDER;
  5707.     top -= TITLEBOXTOP + MAJORBORDER;
  5708.  
  5709.     /*Make the color wheel*/
  5710.     colorWheel = NewColorWheel(left, left + COLORWHEELWIDTH,
  5711.             top - COLORWHEELWIDTH, top, "Text Color");
  5712.     SetVar(colorWheel, PARENT, panel);
  5713.     PrefixList(contents, colorWheel);
  5714.     AssocColorControlWithVar(colorWheel, display, COLOR);
  5715.     SetVar(colorWheel, HELPSTRING, NewString("This color wheel controls the \
  5716. hue and saturation of the color used to draw the text and lines in the palette legend.  \
  5717. The final color is a combination of this hue and saturation and the value, or brightness, \
  5718. given by the Value slider."));
  5719.     
  5720.     /*Make the text box below*/
  5721.     textBox = NewTextBox(left, left + COLORWHEELWIDTH,
  5722.             top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
  5723.             top - COLORWHEELWIDTH - TEXTBOXSEP,
  5724.             PLAIN, "Text Color Label", "Color");
  5725.     SetVar(textBox, PARENT, panel);
  5726.     PrefixList(contents, textBox);
  5727.     SetTextAlign(textBox, CENTERALIGN);
  5728.  
  5729.     /*Make the brightness slider*/
  5730.     slider = NewSlider(right - SLIDERWIDTH, right, 
  5731.                top - COLORWHEELWIDTH, top,
  5732.                PLAIN, "Text Color Value");
  5733.     SetVar(slider, PARENT, panel);
  5734.     PrefixList(contents, slider);
  5735.     SetSliderRange(slider, 1.0, 0.0, 0.0);
  5736.     AssocBrightnessControlWithVar(slider, display, COLOR);
  5737.     SetVar(slider, HELPSTRING, NewString("This slider controls the \
  5738. value, or brightness, of the color used to draw the text and lines in the palette legend.  \
  5739. The final color is a combination of this value and the hue and saturation \
  5740. given by the Color color wheel."));
  5741.  
  5742.     /*Make the text box below*/
  5743.     textBox = NewTextBox(right - SLIDERWIDTH - MAJORBORDER, right + MAJORBORDER,
  5744.             top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
  5745.             top - COLORWHEELWIDTH - TEXTBOXSEP,
  5746.             PLAIN, "Text Value Label", "Value");
  5747.     SetVar(textBox, PARENT, panel);
  5748.     PrefixList(contents, textBox);
  5749.     SetTextAlign(textBox, CENTERALIGN);
  5750.  
  5751.     left -= MINORBORDER;    
  5752.     right += MINORBORDER;
  5753.     /*Make the check box*/
  5754.     top -= COLORWHEELWIDTH + TEXTBOXSEP + TEXTBOXHEIGHT + MINORBORDER;
  5755.     if (!GetVar(display, COLORBYFIELD))
  5756.     {
  5757.         SetVar(display, COLORBYFIELD, ObjFalse);
  5758.     }
  5759.     checkBox = NewCheckBox(left, right, 
  5760.         top - CHECKBOXHEIGHT, top,
  5761.         "Color Text by Palette", GetPredicate(display, COLORBYFIELD));
  5762.     SetVar(checkBox, PARENT, panel);
  5763.     AssocDirectControlWithVar(checkBox, display, COLORBYFIELD);    
  5764.     PrefixList(contents, checkBox);
  5765.     SetVar(checkBox, HELPSTRING, NewString("This check box controls \
  5766. how the numbers in the palette legend are colored.  If the box is checked, the \
  5767. numbers are colored according to the values they represent.  If the box is not \
  5768. checked, the numbers are colored with the same color used for the lines in the \
  5769. legend."));
  5770.     
  5771.     /*Make the background controls*/
  5772.     top = DSPPALWINHEIGHT - MAJORBORDER;
  5773.     right = DSPPALWINWIDTH - MAJORBORDER;
  5774.     left = right - (4 * MAJORBORDER + COLORWHEELWIDTH + SLIDERWIDTH);
  5775.     
  5776.     titleBox = NewTitleBox(left, right,
  5777.             top - TITLEBOXTOP - MAJORBORDER - 2 * MINORBORDER - COLORWHEELWIDTH - CHECKBOXHEIGHT - TEXTBOXHEIGHT - TEXTBOXSEP,
  5778.             top, "Background");
  5779.     SetVar(titleBox, PARENT, panel);
  5780.     PrefixList(contents, titleBox);
  5781.     left += MAJORBORDER;
  5782.     right -= MAJORBORDER;
  5783.     top -= TITLEBOXTOP + MAJORBORDER;
  5784.  
  5785.     /*Make the color wheel*/
  5786.     colorWheel = NewColorWheel(left, left + COLORWHEELWIDTH,
  5787.             top - COLORWHEELWIDTH, top, "Background Color");
  5788.     SetVar(colorWheel, PARENT, panel);
  5789.     PrefixList(contents, colorWheel);
  5790.     AssocColorControlWithVar(colorWheel, display, BACKGROUND);
  5791.     SetVar(colorWheel, HELPSTRING, NewString("This color wheel controls the \
  5792. hue and saturation of the color used to draw the background of the palette legend.  \
  5793. The final color is a combination of this hue and saturation and the value, or brightness, \
  5794. given by the Value slider."));
  5795.     
  5796.     /*Make the text box below*/
  5797.     textBox = NewTextBox(left, left + COLORWHEELWIDTH,
  5798.             top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
  5799.             top - COLORWHEELWIDTH - TEXTBOXSEP,
  5800.             PLAIN, "Background Color Label", "Color");
  5801.     SetVar(textBox, PARENT, panel);
  5802.     PrefixList(contents, textBox);
  5803.     SetTextAlign(textBox, CENTERALIGN);
  5804.  
  5805.     /*Make the brightness slider*/
  5806.     slider = NewSlider(right - SLIDERWIDTH, right, 
  5807.                top - COLORWHEELWIDTH, top,
  5808.                PLAIN, "Background Value");
  5809.     SetVar(slider, PARENT, panel);
  5810.     PrefixList(contents, slider);
  5811.     SetSliderRange(slider, 1.0, 0.0, 0.0);
  5812.     AssocBrightnessControlWithVar(slider, display, BACKGROUND);
  5813.     SetVar(slider, HELPSTRING, NewString("This slider controls the \
  5814. value, or brightness, of the color used to draw the background of the palette legend.  \
  5815. The final color is a combination of this value and the hue and saturation \
  5816. given by the Color color wheel."));
  5817.  
  5818.     /*Make the text box below*/
  5819.     textBox = NewTextBox(right - SLIDERWIDTH - MAJORBORDER, right + MAJORBORDER,
  5820.             top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
  5821.             top - COLORWHEELWIDTH - TEXTBOXSEP,
  5822.             PLAIN, "Background Value Label", "Value");
  5823.     SetVar(textBox, PARENT, panel);
  5824.     PrefixList(contents, textBox);
  5825.     SetTextAlign(textBox, CENTERALIGN);
  5826.  
  5827.     left -= MINORBORDER;    
  5828.     right += MINORBORDER;
  5829.     /*Make the check box*/
  5830.     top -= COLORWHEELWIDTH + TEXTBOXSEP + TEXTBOXHEIGHT + MINORBORDER;
  5831.     checkBox = NewCheckBox(left, right, 
  5832.         top - CHECKBOXHEIGHT, top,
  5833.         "No Background", hasBackground ? false : true);
  5834.     SetVar(checkBox, PARENT, panel);
  5835.     PrefixList(contents, checkBox);
  5836.     AssocInhibitControlWithVar(checkBox, display, BACKGROUND, NewInt(UIBLACK));
  5837.     SetVar(checkBox, HELPSTRING, NewString("This checkbox controls whether \
  5838. a background is shown.  If it is selected, no background is shown, and the \
  5839. objects behind can be seen."));
  5840.  
  5841.     top -= CHECKBOXHEIGHT + MINORBORDER + MINORBORDER;
  5842.     left = MAJORBORDER;
  5843.     right = DSPPALWINWIDTH - MAJORBORDER;
  5844.  
  5845.     /*Make checkbox for show missing*/
  5846.     checkBox = NewCheckBox(left, (left + right) / 2, 
  5847.         top - CHECKBOXHEIGHT, top,
  5848.         "Show Missing", GetPredicate(display, SHOWMISSING));
  5849.     if (!GetVar(display, SHOWMISSING))
  5850.     {
  5851.         SetVar(display, SHOWMISSING, ObjFalse);
  5852.     }
  5853.     SetVar(checkBox, PARENT, panel);
  5854.     PrefixList(contents, checkBox);
  5855.     AssocDirectControlWithVar(checkBox, display, SHOWMISSING);    
  5856.     SetVar(checkBox, HELPSTRING, NewString("This check box controls \
  5857. whether an entry for Missing data is shown in the palette legend."));
  5858.  
  5859.     /*Make checkbox for show Over and Under*/
  5860.     checkBox = NewCheckBox((left + right) / 2, right, 
  5861.         top - CHECKBOXHEIGHT, top,
  5862.         "Show Over and Under", GetPredicate(display, SHOWOVERUNDER));
  5863.     SetVar(checkBox, PARENT, panel);
  5864.     PrefixList(contents, checkBox);
  5865.     if (!GetVar(display, SHOWOVERUNDER))
  5866.     {
  5867.         SetVar(display, SHOWOVERUNDER, ObjFalse);
  5868.     }
  5869.     AssocDirectControlWithVar(checkBox, display, SHOWOVERUNDER);    
  5870.     SetVar(checkBox, HELPSTRING, NewString("This check box controls \
  5871. whether entries for Over and Under data are shown in the palette legend."));
  5872.  
  5873.     top -= CHECKBOXHEIGHT + MINORBORDER;
  5874.  
  5875.     /*Make checkbox for show minor tics*/
  5876.     checkBox = NewCheckBox(left, (left + right) / 2, 
  5877.         top - CHECKBOXHEIGHT, top,
  5878.         "Show Minor Tics", GetPredicate(display, SHOWMINORTICS));
  5879.     SetVar(checkBox, PARENT, panel);
  5880.     PrefixList(contents, checkBox);
  5881.     if (!GetVar(display, SHOWMINORTICS))
  5882.     {
  5883.         SetVar(display, SHOWMINORTICS, ObjFalse);
  5884.     }
  5885.     AssocDirectControlWithVar(checkBox, display, SHOWMINORTICS);    
  5886.     SetVar(checkBox, HELPSTRING, NewString("This check box controls \
  5887. whether minor tic marks are shown in the palette legend in addition to major \
  5888. tic marks and numbers."));
  5889.  
  5890.     /*Make checkbox for numbers only*/
  5891.     checkBox = NewCheckBox((left + right) / 2, right,
  5892.         top - CHECKBOXHEIGHT, top,
  5893.         "Numbers Only", GetPredicate(display, NUMBERSONLY));
  5894.     SetVar(checkBox, PARENT, panel);
  5895.     PrefixList(contents, checkBox);
  5896.     if (!GetVar(display, NUMBERSONLY))
  5897.     {
  5898.         SetVar(display, NUMBERSONLY, ObjFalse);
  5899.     }
  5900.     AssocDirectControlWithVar(checkBox, display, NUMBERSONLY);    
  5901.     SetVar(checkBox, HELPSTRING, NewString("When this check box is down, \
  5902. only the numbers are shown in the palette legend.  This is useful in conjunction \
  5903. with the \"Color text by palette\" check box."));
  5904.     }
  5905.     return (ObjPtr) controlWindow;
  5906. }
  5907.  
  5908.  
  5909. #ifdef PROTO
  5910. void ColorModelFromString(ObjPtr palette, char *model)
  5911. #else
  5912. void ColorModelFromString(palette, model)
  5913. ObjPtr palette;
  5914. char *model;
  5915. #endif
  5916. /*Sets the color model of palette to model*/
  5917. {
  5918.     ObjPtr colorBar;
  5919.     ObjPtr var;
  5920.     int nColors;
  5921.     int whichColorModel;
  5922.  
  5923.     for (whichColorModel = 0; whichColorModel < NCOLORMODELS; ++whichColorModel)
  5924.     {
  5925.     if (0 == strcmp2(model, colorModelNames[whichColorModel])) break;
  5926.     }
  5927.     if (whichColorModel >= NCOLORMODELS) return;
  5928.  
  5929.     colorBar = GetVar((ObjPtr) palette, COLORBAR);
  5930.     if (!colorBar)
  5931.     {
  5932.     return;
  5933.     }
  5934.  
  5935.     SetVar(palette, COLORMODEL, NewInt(whichColorModel));
  5936.  
  5937.     var = GetIntVar("ColorModelFromString", palette, NCOLORS);
  5938.     if (!var) return;
  5939.     nColors = GetInt(var);
  5940.  
  5941.     CopyColorsToComponents(palette);
  5942.  
  5943.     ChangedValue(colorBar);
  5944.     ImInvalid(colorBar);
  5945.  
  5946.     /*Set the edit tool to free form*/
  5947.     ResetColorBarTools(colorBar);
  5948. }
  5949.  
  5950. static ObjPtr ToRGB(palette)
  5951. ObjPtr palette;
  5952. /*Makes a palette go to RGB*/
  5953. {
  5954.     ColorModelFromString(palette, "RGB");
  5955. }
  5956.  
  5957. static ObjPtr ToYIQ(palette)
  5958. ObjPtr palette;
  5959. /*Makes a palette go to YIQ*/
  5960. {
  5961.     ColorModelFromString(palette, "YIQ");
  5962. }
  5963.  
  5964. static ObjPtr ToHSV(palette)
  5965. ObjPtr palette;
  5966. /*Makes a palette go to HSV*/
  5967. {
  5968.     ColorModelFromString(palette, "HSV");
  5969. }
  5970.  
  5971. static ObjPtr ToHLS(palette)
  5972. ObjPtr palette;
  5973. /*Makes a palette go to HLS*/
  5974. {
  5975.     ColorModelFromString(palette, "HLS");
  5976. }
  5977.  
  5978. static ObjPtr ShowPaletteControls(palette, windowName)
  5979. ObjPtr palette;
  5980. char *windowName;
  5981. /*Makes a new control window to control a palette*/
  5982. {
  5983.     WinInfoPtr controlWindow;
  5984.     ObjPtr var;
  5985.     ObjPtr panel;
  5986.     ObjPtr corral;
  5987.     ObjPtr contents;
  5988.     WinInfoPtr dialogExists;
  5989.     int left, right, bottom, top;
  5990.  
  5991.     GetTemplateBounds(PaletteTemplate,  "Panel",  &left,  &right,  &bottom,  &top);
  5992.     dialogExists = DialogExists((WinInfoPtr) palette, NewString("Controls"));
  5993.     controlWindow = GetDialog((WinInfoPtr) palette, NewString("Controls"), windowName, 
  5994.     right - left, top - bottom, SCRWIDTH, SCRHEIGHT, WINUI);
  5995.     
  5996.     if (!dialogExists)
  5997.     {
  5998.     long info;
  5999.     ObjPtr value;
  6000.     int k;    
  6001.     ObjPtr checkBox, icon, name, colorBar, titleBox, textBox, button;
  6002.     ObjPtr colorWheel, slider, fullCompList, compList, radioGroup;
  6003.     char numBuf[200];
  6004.     char *s;
  6005.  
  6006.     SetVar((ObjPtr) controlWindow, REPOBJ, palette);
  6007.  
  6008.     /*Set help string*/
  6009.     SetVar((ObjPtr) controlWindow, HELPSTRING, NewString("This window \
  6010. shows controls for a color palette.  For information about any of the controls \
  6011. in the window, use Help In Context on the control.\n"));
  6012.  
  6013.     /*Add in a panel*/
  6014.     panel = TemplatePanel(PaletteTemplate, "Panel");
  6015.     if (!panel)
  6016.     {
  6017.         return ObjFalse;
  6018.     }
  6019.     contents = GetVar((ObjPtr) controlWindow, CONTENTS);
  6020.     PrefixList(contents, panel);
  6021.     SetVar(panel, PARENT, (ObjPtr) controlWindow);
  6022.  
  6023.     contents = GetVar(panel, CONTENTS);
  6024.  
  6025.     /*Create a color bar to add in later*/
  6026.     left = 2 * MAJORBORDER + PCWINLSIDE;
  6027.     right = PCWINWIDTH - MAJORBORDER;
  6028.     bottom = MAJORBORDER + PCBARUP;
  6029.     top = bottom + PCBARHEIGHT;
  6030.  
  6031.     colorBar = TemplateColorBar(PaletteTemplate, "Palette Colors");
  6032.     fullCompList = NewList();    /*List of buttons active on full or component*/
  6033.     compList = NewList();        /*List of buttons active on component*/
  6034.     SetVar(colorBar, FULLCOMPBUTTONS, fullCompList);
  6035.     SetVar(colorBar, COMPBUTTONS, compList);
  6036.     SetVar(colorBar, EDITMODE, NewInt(PT_FREEFORM));        /*Freeform editor*/
  6037.     SetVar((ObjPtr) controlWindow, COLORBAR, colorBar);
  6038.     SetVar(colorBar, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT + STICKYBOTTOM + STICKYTOP));
  6039.     SetVar(palette, COLORBAR, colorBar);
  6040.  
  6041.     /*Ramp button*/
  6042.      button = TemplateButton(PaletteTemplate, "Ramp");
  6043.     PrefixList(contents, button);
  6044.     SetVar(button, PARENT, panel);
  6045.     SetVar(button, REPOBJ, palette);
  6046.     SetVar(button, COLORBAR, colorBar);
  6047.     SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
  6048.     SetVar(button, PALETTEFUNC, NewInt(PF_RAMP));
  6049.     ActivateButton(button, false);
  6050.     PrefixList(fullCompList, button);
  6051.     SetVar(button, HELPSTRING,
  6052.         NewString("This button interpolates between the selected \
  6053. colors to make a smooth color ramp.  When a range in the full color bar is \
  6054. selected, all components will be interpolated.  When a range of a single component \
  6055. is selected, just that component will be interpolated.\n"));
  6056.     SetVar(button, HALTHELP, ObjTrue); 
  6057.  
  6058.     /*Reverse button*/
  6059.      button = TemplateButton(PaletteTemplate, "Reverse");
  6060.     PrefixList(contents, button);
  6061.     SetVar(button, PARENT, panel);
  6062.     SetVar(button, REPOBJ, palette);
  6063.     SetVar(button, COLORBAR, colorBar);
  6064.     SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
  6065.     SetVar(button, PALETTEFUNC, NewInt(PF_REVERSE));
  6066.     ActivateButton(button, false);
  6067.     PrefixList(fullCompList, button);
  6068.     SetVar(button, HELPSTRING,
  6069.         NewString("This button reverses the range of selected colors.  \
  6070. When a range in the full color bar is \
  6071. selected, all components will be reversed.  When a range of a single component \
  6072. is selected, just that component will be reversed.\n")); 
  6073.     SetVar(button, HALTHELP, ObjTrue); 
  6074.  
  6075.     /*Ruffle button*/
  6076.      button = TemplateButton(PaletteTemplate, "Ruffle");
  6077.     PrefixList(contents, button);
  6078.     SetVar(button, PARENT, panel);
  6079.     SetVar(button, REPOBJ, palette);
  6080.     SetVar(button, COLORBAR, colorBar);
  6081.     SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
  6082.     SetVar(button, PALETTEFUNC, NewInt(PF_RUFFLE));
  6083.     ActivateButton(button, false);
  6084.     PrefixList(fullCompList, button);
  6085.     SetVar(button, HELPSTRING,
  6086.         NewString("This button ruffles the selected colors.  \
  6087. This reverses short sections of colors, producing a contour-like effect.  When a range of a single component \
  6088. is selected, just that component will be ruffled.\n")); 
  6089.     SetVar(button, HALTHELP, ObjTrue); 
  6090.  
  6091.     /*Smooth button*/
  6092.      button = TemplateButton(PaletteTemplate, "Smooth");
  6093.     PrefixList(contents, button);
  6094.     SetVar(button, PARENT, panel);
  6095.     SetVar(button, REPOBJ, palette);
  6096.     SetVar(button, COLORBAR, colorBar);
  6097.     SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
  6098.     SetVar(button, PALETTEFUNC, NewInt(PF_SMOOTH));
  6099.     ActivateButton(button, false);
  6100.     PrefixList(fullCompList, button);
  6101.     SetVar(button, HELPSTRING,
  6102.         NewString("This button smooths the selected colors.  \
  6103. This will reduce the abrupt changes which can worsen artifacts such as Mach bands.  \
  6104. You can smooth a range more by pressing the button repeatedly.  \
  6105. When a range in the full color bar is \
  6106. selected, all components will be smoothed.  When a range of a single component \
  6107. is selected, just that component will be smoothed.\n")); 
  6108.     SetVar(button, HALTHELP, ObjTrue); 
  6109.  
  6110.     /*Sharpen button*/
  6111.      button = TemplateButton(PaletteTemplate, "Sharpen");
  6112.     PrefixList(contents, button);
  6113.     SetVar(button, PARENT, panel);
  6114.     SetVar(button, REPOBJ, palette);
  6115.     SetVar(button, COLORBAR, colorBar);
  6116.     SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
  6117.     SetVar(button, PALETTEFUNC, NewInt(PF_SHARPEN));
  6118.     ActivateButton(button, false);
  6119.     PrefixList(fullCompList, button);
  6120.     SetVar(button, HELPSTRING,
  6121.         NewString("This button sharpens color distinction within the selected colors.  \
  6122. This may increase artifacts such as Mach bands.  Sharpen and Smooth are not \
  6123. quite inverse operations, but they have roughly opposite effects.  Sharpen will \
  6124. amplify noise and variations in the colors, which will become evident after the \
  6125. button is pressed three or four times.  \
  6126. When a range in the full color bar is \
  6127. selected, all components will be sharpened.  When a range of a single component \
  6128. is selected, just that component will be sharpened.\n")); 
  6129.     SetVar(button, HALTHELP, ObjTrue); 
  6130.  
  6131.     /*Put in the min and max text boxes below*/
  6132.     textBox = TemplateTextBox(PaletteTemplate, "Field Min", EDITABLE + WITH_PIT + ONE_LINE, "");
  6133.     SetVar(textBox, PARENT, panel);
  6134.     PrefixList(contents, textBox);
  6135.     SetTextAlign(textBox, RIGHTALIGN);
  6136.     SetVar(textBox, HELPSTRING, NewString("This text box shows the maximum \
  6137. field value represented by the color table.  Any value above this will use the \
  6138. overflow color.  To change this value, enter the new number and press the Enter \
  6139. key."));
  6140.     
  6141.     SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
  6142.     AssocIndexedTextRealControlWithVar(
  6143.         textBox, palette, MINMAX, 0, minusInf, plusInf, 
  6144.         0);
  6145.  
  6146.     /*Min legend*/
  6147.     textBox = TemplateTextBox(PaletteTemplate, "Field Min Legend", 0, "Minimum:");
  6148.     SetVar(textBox, PARENT, panel);
  6149.     PrefixList(contents, textBox);
  6150.     SetTextAlign(textBox, RIGHTALIGN);
  6151.     SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
  6152.  
  6153.     /*Max text box*/
  6154.     textBox = TemplateTextBox(PaletteTemplate, "Field Max", EDITABLE + WITH_PIT + ONE_LINE, "");
  6155.     SetVar(textBox, PARENT, panel);
  6156.     PrefixList(contents, textBox);
  6157.     SetTextAlign(textBox, RIGHTALIGN);
  6158.     SetVar(textBox, HELPSTRING, NewString("This text box shows the minimum \
  6159. field value represented by the color table.  Any value below this will use the \
  6160. underflow color.  To change this value, enter the new number and press the Enter \
  6161. key."));
  6162.     SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
  6163.      AssocIndexedTextRealControlWithVar(
  6164.         textBox, palette, MINMAX, 1, minusInf, plusInf, 
  6165.         0);
  6166.  
  6167.     /*Max legend*/
  6168.     textBox = TemplateTextBox(PaletteTemplate, "Field Max Legend", 0, "Maximum:");
  6169.     SetVar(textBox, PARENT, panel);
  6170.     PrefixList(contents, textBox);
  6171.     SetTextAlign(textBox, RIGHTALIGN);
  6172.     SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
  6173.  
  6174.     /*nColors text box*/
  6175.     left = MAJORBORDER;
  6176.     textBox = TemplateTextBox(PaletteTemplate, "N Colors", EDITABLE + WITH_PIT + ONE_LINE, "");
  6177.     SetVar(textBox, PARENT, panel);
  6178.     PrefixList(contents, textBox);
  6179.     SetTextAlign(textBox, RIGHTALIGN);
  6180.     SetVar(textBox, HELPSTRING, NewString("This text box shows the number of colors \
  6181. in the palette, including the missing data, underflow, and overflow entries.  \
  6182. To change the number of colors, enter the new number and press the Enter \
  6183. key.  The palette will be resampled with the new number of colors.  When increasing \
  6184. the number of colors, it is sometimes useful to do a Smooth operation afterward \
  6185. to smooth out the changes."));
  6186.     AssocTextIntControlWithVar(
  6187.         textBox, palette, NCOLORS, 5.0, plusInf, 
  6188.         TR_INT_ONLY | TR_NE_TOP);
  6189.     SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
  6190.  
  6191.     /*nColors legend*/
  6192.     textBox = TemplateTextBox(PaletteTemplate, "NColors Legend", 0, "Colors");
  6193.     SetVar(textBox, PARENT, panel);
  6194.     PrefixList(contents, textBox);
  6195.     SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
  6196.  
  6197.     /*Add in the left color control group*/
  6198.     left = MINORBORDER;
  6199.     right = left + PCWINLSIDE;
  6200.     top = PCWINHEIGHT - MINORBORDER;
  6201.  
  6202.     SetVar(palette, KEPTPALETTE, CloneObject(palette));
  6203.  
  6204.     bottom = MINORBORDER + PCBARUP;
  6205.     top = bottom + COLORWHEELWIDTH + TEXTBOXHEIGHT + TEXTBOXSEP;    
  6206.     /*Color wheel*/
  6207.     colorWheel = TemplateColorWheel(PaletteTemplate, "Color");
  6208.     SetVar(colorWheel, PARENT, panel);
  6209.     PrefixList(contents, colorWheel);
  6210.     SetVar(colorWheel, REPOBJ, palette);
  6211.     ActivateColorWheel(colorWheel, false);
  6212.     SetVar(colorWheel, VALUE, false);
  6213.     SetVar(colorWheel, HELPSTRING,
  6214.         NewString("This color wheel controls the hue and saturation of the \
  6215. entire range of selected colors.  When you use this control, the entire range \
  6216. will be set to the new color."));
  6217.     SetVar(colorWheel, HALTHELP, ObjTrue);
  6218.  
  6219.     /*Color wheel text box*/
  6220.     textBox = TemplateTextBox(PaletteTemplate, "HS Text", 0, "Color");
  6221.     PrefixList(contents, textBox);
  6222.     SetVar(textBox, PARENT, panel);
  6223.     SetTextAlign(textBox, CENTERALIGN);
  6224.  
  6225.     /*Slider*/
  6226.     slider = TemplateSlider(PaletteTemplate, "Intensity", PLAIN);
  6227.     PrefixList(contents, slider);
  6228.     SetVar(slider, PARENT, panel);
  6229.     SetSliderRange(slider, 1.0, 0.0, 0.0);
  6230.     SetSliderValue(slider, 1.0);
  6231.     ActivateSlider(slider, false);
  6232.     SetVar(slider, HELPSTRING, NewString("This slider controls the intensity of \
  6233. the colors selected in the color bar control to the right.  When a range of colors is selected, this slider controls the value \
  6234. of the colors represented in the Hue/Saturation/Value color model.  \
  6235. When a range of a single color component is selected, it controls the intensity \
  6236. of that component."));
  6237.     SetVar(slider, HALTHELP, ObjTrue);
  6238.  
  6239.     /*Slider text box*/
  6240.     textBox = TemplateTextBox(PaletteTemplate, "Intensity Text", 0, "Intensity");
  6241.     PrefixList(contents, textBox);
  6242.     SetVar(textBox, PARENT, panel);
  6243.     SetTextAlign(textBox, CENTERALIGN);
  6244.  
  6245.     /*Link slider and color wheel*/
  6246.     SetVar(slider, COLORWHEEL, colorWheel);
  6247.     SetVar(colorWheel, SLIDER, slider);
  6248.  
  6249.     /*Link the color wheels to the color bar*/
  6250.     SetVar(slider, COLORBAR, colorBar);
  6251.     SetVar(colorWheel, COLORBAR, colorBar);
  6252.  
  6253.     /*Waveform tools*/
  6254.     top = MAJORBORDER + PCBARHEIGHT + PCBARUP;
  6255.     bottom = top - (TITLEBOXTOP + 2 * MINORBORDER + VWTOOLBORDER + 2 * SMALLICONBUTTONSIZE);
  6256.     titleBox = TemplateTitleBox(PaletteTemplate, "Edit Component");
  6257.     PrefixList(contents, titleBox);
  6258.     SetVar(titleBox, PARENT, panel);
  6259.     left += MINORBORDER;
  6260.     right -= MINORBORDER;
  6261.     bottom += MINORBORDER;
  6262.     top -= TITLEBOXTOP + MINORBORDER;
  6263.     
  6264.     /*Icons*/
  6265.     radioGroup = NewRadioButtonGroup("Waveform Tools");
  6266.     SetVar(colorBar, TOOLGROUP, radioGroup);
  6267.     SetVar(radioGroup, HELPSTRING,
  6268.         NewString("This is a group of tools that allow you to edit the \
  6269. currently selected color component.  \
  6270. To use one of these tools, \
  6271. first select a range in any one of the color components by dragging through the range \
  6272. and then press the button of the tool \
  6273. you want to use."));
  6274.     SetVar(radioGroup, PARENT, panel);
  6275.     PrefixList(contents, radioGroup);
  6276.     SetVar(radioGroup, HALTHELP, ObjTrue);
  6277.  
  6278.     /*Freeform*/
  6279.     button = TemplateIconButton(PaletteTemplate, "Free form", ICONFREEFORM, UIYELLOW, BS_PLAIN);
  6280.     AddRadioButton(radioGroup, button);
  6281.     ActivateButton(button, false);
  6282.     SetVar(colorBar, FREEFORMBUTTON, button);
  6283.     SetVar(button, HELPSTRING, NewString("This button selects the \
  6284. free form tool, which allows you to edit the waveform simply by clicking \
  6285. and drawing in the magnified readout at the top of the color bar to the right.  \
  6286. Hold down the Shift key to constrain motion to just the horizontal or \
  6287. vertical direction."));
  6288.  
  6289.     /*Sine*/
  6290.     button = TemplateIconButton(PaletteTemplate, "Sine", ICONSINE, UIYELLOW, BS_PLAIN);
  6291.     AddRadioButton(radioGroup, button);
  6292.     ActivateButton(button, false);
  6293.     PrefixList(compList, button);
  6294.     SetVar(button, HELPSTRING, NewString("This button selects the \
  6295. sine wave tool, which fills the entire selected range with a sine wave.  \
  6296. When this tool is selected, a yellow box in the magnified readout lets you \
  6297. change the period, phase, and position of the wave."));
  6298.  
  6299.     /*Triangle*/
  6300.     button = TemplateIconButton(PaletteTemplate, "Triangle", ICONTRIANGLE, UIYELLOW, BS_PLAIN);
  6301.     AddRadioButton(radioGroup, button);
  6302.     ActivateButton(button, false);
  6303.     PrefixList(compList, button);
  6304.     SetVar(button, HELPSTRING, NewString("This button selects the \
  6305. triangle wave tool, which fills the entire selected range with a triangle wave.  \
  6306. When this tool is selected, a yellow box in the magnified readout lets you \
  6307. change the period, phase, and position of the wave."));
  6308.  
  6309.     /*Sawtooth*/
  6310.     button = TemplateIconButton(PaletteTemplate, "Sawtooth", ICONSAWTOOTH, UIYELLOW, BS_PLAIN);
  6311.     AddRadioButton(radioGroup, button);
  6312.     ActivateButton(button, false);
  6313.     PrefixList(compList, button);
  6314.     SetVar(button, HELPSTRING, NewString("This button selects the \
  6315. sawtooth wave tool, which fills the entire selected range with a sawtooth wave.  \
  6316. When this tool is selected, a yellow box in the magnified readout lets you \
  6317. change the period, phase, and position of the wave."));
  6318.  
  6319.     /*Toothsaw*/
  6320.     button = TemplateIconButton(PaletteTemplate, "Toothsaw", ICONTOOTHSAW, UIYELLOW, BS_PLAIN);
  6321.     AddRadioButton(radioGroup, button);
  6322.     ActivateButton(button, false);
  6323.     PrefixList(compList, button);
  6324.     SetVar(button, HELPSTRING, NewString("This button selects the \
  6325. reverse sawtooth wave tool, which fills the entire selected range with a reverse sawtooth wave.  \
  6326. When this tool is selected, a yellow box in the magnified readout lets you \
  6327. change the period, phase, and position of the wave."));
  6328.  
  6329.     /*Square*/
  6330.     button = TemplateIconButton(PaletteTemplate, "Square", ICONSQUARE, UIYELLOW, BS_PLAIN);
  6331.     AddRadioButton(radioGroup, button);
  6332.     ActivateButton(button, false);
  6333.     PrefixList(compList, button);
  6334.     SetVar(button, HELPSTRING, NewString("This button selects the \
  6335. square wave tool, which fills the entire selected range with a square wave.  \
  6336. When this tool is selected, a yellow box in the magnified readout lets you \
  6337. change the period, phase, and position of the wave."));
  6338.  
  6339.     SetValue(radioGroup, NewInt(PT_FREEFORM));
  6340.     SetVar(radioGroup, REPOBJ, colorBar);
  6341.     SetMethod(radioGroup, CHANGEDVALUE, ChangeColorTool);
  6342.  
  6343.     /*Now add in the color bar*/
  6344.     SetMethod(colorBar, MAKE1HELPSTRING, MakePaletteBarHelp);
  6345.     SetVar(colorBar, HALTHELP, ObjTrue);
  6346.     PrefixList(contents, colorBar);
  6347.     SetVar(colorBar, PARENT, panel);
  6348.     SetVar(colorBar, REPOBJ, palette);
  6349.         SetVar(colorBar, SLIDER, slider);
  6350.     SetVar(colorBar, COLORWHEEL, colorWheel);
  6351.     SetVar(panel, COLORBAR, colorBar);
  6352.     value = NewRealArray(1, 3L);
  6353.     ((real *) ELEMENTS(value))[0] = 0.0;
  6354.     ((real *) ELEMENTS(value))[1] = 0.0;
  6355.     ((real *) ELEMENTS(value))[2] = 0.0;
  6356.     SetMethod(colorBar, CHANGEDVALUE, ChangePaletteBar);
  6357.     SetValue(colorBar, value);
  6358.     ReinitColorBar(colorBar);
  6359.  
  6360.     /*Give the color wheels and sliders changedValue routines*/
  6361.     SetMethod(colorWheel, CHANGEDVALUE, ChangePaletteColorWheel);
  6362.     SetMethod(slider, CHANGEDVALUE, ChangePaletteSlider);
  6363.     }
  6364.     return (ObjPtr) controlWindow;
  6365. }
  6366.  
  6367. #ifdef PROTO
  6368. int ChooseSelectionColor(ObjPtr object)
  6369. #else
  6370. int ChooseSelectionColor(object)
  6371. ObjPtr object;
  6372. #endif
  6373. /*Chooses a selection color to contrast with object's COLOR and BACKGROUND*/
  6374. {
  6375.     ObjPtr color, background, oneOnly;
  6376.     float target[3];
  6377.     float r1, g1, b1, r2, g2, b2, t, b;
  6378.     real *elements;
  6379.  
  6380.     color = GetVar(object, COLOR);
  6381.     background = GetVar(object, BACKGROUND);
  6382.  
  6383.     if (!color && !background)
  6384.     {
  6385.     /*Nothing there, so use UIWHITE*/
  6386.     return UIWHITE;
  6387.     }
  6388.  
  6389.     if (color)
  6390.     {
  6391.     if (IsInt(color))
  6392.     {
  6393.         int c;
  6394.         c = GetInt(color);
  6395.         r1 = ((float) uiColors[c][0]) / 255.0;
  6396.         g1 = ((float) uiColors[c][1]) / 255.0;
  6397.         b1 = ((float) uiColors[c][2]) / 255.0;
  6398.     }
  6399.     else if (IsRealArray(color) && RANK(color) == 1 && DIMS(color)[0] == 3)
  6400.     {
  6401.         elements = ELEMENTS(color);
  6402.         r1 = elements[0];
  6403.         g1 = elements[1];
  6404.         b1 = elements[2];
  6405.     }
  6406.     else
  6407.     {
  6408.         ReportError("ChooseSelectionColor", "Bad color");
  6409.         return UIWHITE;
  6410.     }
  6411.     }
  6412.     else
  6413.     {
  6414.     r1 = g1 = b1 = 0.0;
  6415.     }
  6416.  
  6417.     if (background)
  6418.     {
  6419.     if (IsInt(background))
  6420.     {
  6421.         int c;
  6422.         c = GetInt(background);
  6423.         r2 = ((float) uiColors[c][0]) / 255.0;
  6424.         g2 = ((float) uiColors[c][1]) / 255.0;
  6425.         b2 = ((float) uiColors[c][2]) / 255.0;
  6426.     }
  6427.     else if (IsRealArray(background) && RANK(background) == 1 && DIMS(background)[0] == 3)
  6428.     {
  6429.         elements = ELEMENTS(background);
  6430.         r2 = elements[0];
  6431.         g2 = elements[1];
  6432.         b2 = elements[2];
  6433.     }
  6434.     else
  6435.     {
  6436.         ReportError("ChooseSelectionColor", "Bad background");
  6437.         return UIWHITE;
  6438.     }
  6439.     }
  6440.     else
  6441.     {
  6442.     r2 = g2 = b2 = 0.0;
  6443.     }
  6444.  
  6445.     /*Try to choose a good target color*/
  6446.  
  6447.     /*First r*/
  6448.     t = MAX(r1, r2);
  6449.     b = MIN(r1, r2);
  6450.  
  6451.     if (t < 0.75) target[0] = 1.0; else target[0] = 0.0;
  6452.  
  6453.     /*Now g*/
  6454.     t = MAX(g1, g2);
  6455.     b = MIN(g1, g2);
  6456.  
  6457.     if (t < 0.75) target[1] = 1.0; else target[1] = 0.0;
  6458.  
  6459.     /*Now b*/
  6460.     t = MAX(b1, b2);
  6461.     b = MIN(b1, b2);
  6462.  
  6463.     if (b > 0.25) target[2] = 0.0; else target[2] = 1.0;
  6464.     return ClosestUIColor(target);
  6465. }
  6466.  
  6467. #ifdef PROTO
  6468. void SetObjectColor(ObjPtr col)
  6469. #else
  6470. void SetObjectColor(col)
  6471. ObjPtr col;
  6472. #endif
  6473. /*If col is an int, sets its ui color.
  6474.   If col is a real 3-array, sets its value
  6475. */
  6476. {
  6477. #ifdef GRAPHICS
  6478.     if (overDraw)
  6479.     {
  6480.     if (IsInt(col) && GetInt(col) == UIBLACK)
  6481.     {
  6482.         color(UIOVERCLEAR);
  6483.     }
  6484.     else
  6485.     {
  6486.         color(UIOVERRED);
  6487.     }
  6488.     }
  6489.     else
  6490.     {
  6491.     if (IsInt(col))
  6492.     {
  6493.     SetUIColor(GetInt(col));
  6494.     }
  6495.     else if (IsRealArray(col) && RANK(col) == 1 && DIMS(col)[0] == 3)
  6496.     {
  6497.     float clr[3];
  6498.     real *elements;
  6499.     elements = ELEMENTS(col);
  6500.     if (drawingMode == DRAW_SCREEN)
  6501.     {
  6502.     clr[0] = elements[0];
  6503.     clr[1] = elements[1];
  6504.     clr[2] = elements[2];
  6505.     RGBC(clr);
  6506.     }
  6507.     else
  6508.     {
  6509.         curRed = elements[0];
  6510.         curGreen = elements[1];
  6511.         curBlue = elements[2];
  6512.     }
  6513.     }
  6514.     else
  6515.     {
  6516.     ReportError("SetObjectColor", "Bad color value");
  6517.     }
  6518.     }
  6519. #endif
  6520. }
  6521.  
  6522. #define PALDISPLAYBORDER    20
  6523. #define PALDISPLAYTEXTWIDTH    0.6
  6524.  
  6525. #define PALDISPLAYVCOLORWIDTH    0.3
  6526. #define PALDISPLAYVCOLORHEIGHT    0.08
  6527.  
  6528. #define PALDISPLAYHCOLORWIDTH    0.12
  6529. #define PALDISPLAYHCOLORHEIGHT    0.6
  6530.  
  6531. ObjPtr DrawPaletteDisplay(display)
  6532. ObjPtr display;
  6533. /*Draws a display*/
  6534. {
  6535. #ifdef GRAPHICS
  6536.     int left, right, bottom, top;
  6537.     int l, r, b, t;
  6538.     int intLeft, intRight, intBottom, intTop;    /*Interior dims*/
  6539.     double halfSpace, ddiff, majorWidth, minorWidth, curValue;
  6540.     int pixel;
  6541.     long temp;
  6542.     int nTics;
  6543.     int k, diff, start;
  6544.     int alignment;
  6545.     Bool drawOverUnder;
  6546.     Bool drawMissing;
  6547.     Bool numbersOnly;
  6548.     Bool drawMinorTics;
  6549.     ObjPtr palette;
  6550.     ObjPtr var;
  6551.     char *textFont;
  6552.     short3 *colors;
  6553.     int beg;
  6554.     int nColors;
  6555.     int textSize;
  6556.     ObjPtr textColor;
  6557.     int minMajorStep;
  6558.     Bool colorByPalette;
  6559.     int boxWidth, boxHeight, stringWidth, stringHeight;
  6560.     real *minmax;
  6561.  
  6562.     Get2DIntBounds(display, &left, &right, &bottom, &top);
  6563.  
  6564.     intLeft = left + PALDISPLAYBORDER;
  6565.     intRight = right - PALDISPLAYBORDER;
  6566.     intBottom = bottom + PALDISPLAYBORDER;
  6567.     intTop = top - PALDISPLAYBORDER;
  6568.  
  6569.     textColor = GetVar(display, COLOR);
  6570.  
  6571.     palette = GetPaletteVar("DrawPaletteDisplay", display, REPOBJ);
  6572.     if (!palette)
  6573.     {
  6574.     return ObjFalse;
  6575.     }
  6576.  
  6577.     MakeVar(palette, COLORS);
  6578.     var = GetVar(palette, COLORS);
  6579.     if (!var)
  6580.     {
  6581.     return ObjFalse;
  6582.     }
  6583.     colors = ELEMENTS(var);
  6584.  
  6585.     if (!rgbp)
  6586.     {
  6587.     var = GetIntVar("DrawPaletteDisplay", palette, BEGCOLOR);
  6588.      if (!var) return ObjFalse;
  6589.     beg = GetInt(var);
  6590.     }
  6591.     else
  6592.     {
  6593.     beg = 0;
  6594.     }
  6595.  
  6596.     var = GetIntVar("DrawPaletteDisplay", palette, NCOLORS);
  6597.     if (!var)
  6598.     {
  6599.     return ObjFalse;
  6600.     }
  6601.     nColors = GetInt(var);
  6602.  
  6603.     var = GetFixedArrayVar("DrawPaletteDisplay", palette, MINMAX, 1, 2L);
  6604.     if (!var)
  6605.     {
  6606.     return ObjFalse;
  6607.     }
  6608.     minmax = ELEMENTS(var);
  6609.  
  6610.     /*Get colorByPalette predicate*/
  6611.     colorByPalette = GetPredicate(display, COLORBYFIELD);
  6612.  
  6613.     /*Get draw portions predicates*/
  6614.     drawOverUnder = GetPredicate(display, SHOWOVERUNDER);
  6615.     drawMissing = GetPredicate(display, SHOWMISSING);
  6616.     numbersOnly = GetPredicate(display, NUMBERSONLY);
  6617.     drawMinorTics = GetPredicate(display, SHOWMINORTICS);
  6618.  
  6619.     /*Set the color palette*/
  6620.     SetPalette(palette);
  6621.  
  6622.     /*Draw the background*/
  6623.     var = GetVar(display, BACKGROUND);
  6624.     if (var)
  6625.     {
  6626.     SetObjectColor(var);
  6627.     FillRect(left, right, bottom, top);
  6628.     }
  6629.  
  6630.     /*Draw the info on the palette itself*/
  6631.     SetObjectColor(textColor);
  6632.  
  6633.     var = GetIntVar("DrawPaletteDisplay", display, MINMAJORSTEP);
  6634.     if (var)
  6635.     {
  6636.     minMajorStep = GetInt(var);
  6637.     }
  6638.     else
  6639.     {
  6640.     minMajorStep = 30;
  6641.     }
  6642.  
  6643.     var = GetStringVar("DrawPaletteDisplay", display, TEXTFONT);
  6644.     if (var)
  6645.     {
  6646.     textFont = GetString(var);
  6647.     }
  6648.     else
  6649.     {
  6650.     textFont = "Helvetica";
  6651.     }
  6652.  
  6653.     var = GetIntVar("DrawPaletteDisplay", display, TEXTSIZE);
  6654.     if (var)
  6655.     {
  6656.     textSize = GetInt(var);
  6657.     }
  6658.     else
  6659.     {
  6660.     textSize = 18;
  6661.     }
  6662.  
  6663.     var = GetIntVar("DrawPaletteDisplay", display, ALIGNMENT);
  6664.     if (var)
  6665.     {
  6666.     alignment = GetInt(var);
  6667.     }
  6668.     else
  6669.     {
  6670.     alignment = CENTERALIGN;
  6671.     }
  6672.  
  6673.     SetupFont(textFont, textSize);
  6674.  
  6675.     stringWidth = (intRight - intLeft) * PALDISPLAYTEXTWIDTH;
  6676.     stringHeight = textSize;
  6677.  
  6678.     if (right - left < top - bottom)
  6679.     {
  6680.     /*It's vertical*/
  6681.     int rangeBot, rangeTop;
  6682.     int x;
  6683.  
  6684.     b = intBottom;
  6685.     t = intTop;
  6686.  
  6687.     boxWidth = (intRight - intLeft) * PALDISPLAYVCOLORWIDTH;
  6688.     boxHeight = (intTop - intBottom) * PALDISPLAYVCOLORHEIGHT;
  6689.  
  6690.     if (drawMissing)
  6691.     {
  6692.         /*Draw the missing data box*/
  6693.         t = b + boxHeight;
  6694.         if (numbersOnly)
  6695.         {
  6696.         l = intLeft;
  6697.         r = intRight;
  6698.         }
  6699.         else
  6700.         {
  6701.         r = intRight;
  6702.         l = r - boxWidth;
  6703.         FrameRect(l, r, b, t);
  6704.         FrameRect(l - 1, r + 1, b - 1, t + 1);
  6705.         if (rgbp)
  6706.         {
  6707.         c3s(colors[0]);
  6708.         }
  6709.         else
  6710.         {
  6711.         color(beg);
  6712.         }
  6713.         FillRect(l + 1, r - 1, b + 1, t - 1);
  6714.         SetObjectColor(textColor);
  6715.  
  6716.         r = intLeft + stringWidth;
  6717.         DrawLine(l, (b + t) / 2, r, (b + t) / 2);
  6718.         DrawLine(l, (b + t) / 2 + 1, r, (b + t) / 2 + 1);
  6719.         l = intLeft;
  6720.         }
  6721.         strcpy(tempStr, "Missing");
  6722.         switch(alignment)
  6723.         {
  6724.         case LEFTALIGN:
  6725.             x = l;
  6726.             break;
  6727.         case CENTERALIGN:
  6728.             x = (l + r - DSPPALETTESTL) / 2;
  6729.             break;
  6730.         case RIGHTALIGN:
  6731.             x = r - DSPPALETTESTL;
  6732.             break;
  6733.     
  6734.         }
  6735.         if (colorByPalette)
  6736.         {
  6737.         SetRealColor(missingData);
  6738.         }
  6739.         DrawAString(alignment, x, (b + t - textSize) / 2, tempStr);
  6740.         if (colorByPalette)
  6741.         {
  6742.         SetObjectColor(textColor);
  6743.         }
  6744.  
  6745.         b = t + MINORBORDER;
  6746.         t = intTop;
  6747.     }
  6748.  
  6749.     if (drawOverUnder)
  6750.     {
  6751.         /*Draw the underflow data box*/
  6752.         t = b + boxHeight;
  6753.         if (numbersOnly)
  6754.         {
  6755.         l = intLeft;
  6756.         r = intRight;
  6757.         }
  6758.         else
  6759.         {
  6760.         r = intRight;
  6761.         l = r - boxWidth;
  6762.         FrameRect(l, r, b, t);
  6763.         FrameRect(l - 1, r + 1, b - 1, t + 1);
  6764.         if (rgbp)
  6765.         {
  6766.         c3s(colors[1]);
  6767.         }
  6768.         else
  6769.         {
  6770.         color(beg + 1);
  6771.         }
  6772.         FillRect(l + 1, r - 1, b + 1, t - 1);
  6773.         SetObjectColor(textColor);
  6774.  
  6775.         r = intLeft + stringWidth;
  6776.         DrawLine(l, (b + t) / 2, r, (b + t) / 2);
  6777.         DrawLine(l, (b + t) / 2 + 1, r, (b + t) / 2 + 1);
  6778.         l = intLeft;
  6779.         }
  6780.         strcpy(tempStr, "Under");
  6781.         switch(alignment)
  6782.         {
  6783.         case LEFTALIGN:
  6784.             x = l;
  6785.             break;
  6786.         case CENTERALIGN:
  6787.             x = (l + r - DSPPALETTESTL) / 2;
  6788.             break;
  6789.         case RIGHTALIGN:
  6790.             x = r - DSPPALETTESTL;
  6791.             break;
  6792.     
  6793.         }
  6794.         if (colorByPalette)
  6795.         {
  6796.         SetRealColor(MINUSINF);
  6797.         }
  6798.         DrawAString(alignment, x, (b + t - textSize) / 2, tempStr);
  6799.         if (colorByPalette)
  6800.         {
  6801.         SetObjectColor(textColor);
  6802.         }
  6803.  
  6804.         b = t + MINORBORDER;
  6805.  
  6806.         /*Draw the overflow data box*/
  6807.         t = intTop;
  6808.         if (numbersOnly)
  6809.         {
  6810.         l = intLeft;
  6811.         r = intRight;
  6812.         }
  6813.         else
  6814.         {
  6815.         r = intRight;
  6816.         l = r - boxWidth;
  6817.         FrameRect(l, r, t - boxHeight, t);
  6818.         FrameRect(l - 1, r + 1, t - boxHeight - 1, t + 1);
  6819.         if (rgbp)
  6820.         {
  6821.         c3s(colors[nColors - 1]);
  6822.         }
  6823.         else
  6824.         {
  6825.         color(beg + nColors - 1);
  6826.         }
  6827.         FillRect(l + 1, r - 1, t - boxHeight + 1, t - 1);
  6828.         SetObjectColor(textColor);
  6829.  
  6830.         r = intLeft + stringWidth;
  6831.         DrawLine(l, t - boxHeight / 2, r, t - boxHeight / 2);
  6832.         DrawLine(l, t - boxHeight / 2 + 1, r, t - boxHeight / 2 + 1);
  6833.         l = intLeft;
  6834.         }
  6835.         strcpy(tempStr, "Over");
  6836.         switch(alignment)
  6837.         {
  6838.         case LEFTALIGN:
  6839.             x = l;
  6840.             break;
  6841.         case CENTERALIGN:
  6842.             x = (l + r - DSPPALETTESTL) / 2;
  6843.             break;
  6844.         case RIGHTALIGN:
  6845.             x = r - DSPPALETTESTL;
  6846.             break;
  6847.     
  6848.         }
  6849.         if (colorByPalette)
  6850.         {
  6851.         SetRealColor(PLUSINF);
  6852.         }
  6853.         DrawAString(alignment, x, t - boxHeight / 2 - textSize / 2, tempStr);
  6854.         if (colorByPalette)
  6855.         {
  6856.         SetObjectColor(textColor);
  6857.         }
  6858.  
  6859.         t = intTop - boxHeight - MINORBORDER;
  6860.     }
  6861.  
  6862.     /*Draw the main section of the display*/
  6863.     r = intRight;
  6864.     l = r - boxWidth;
  6865.     if (!numbersOnly)
  6866.     {
  6867.         FrameRect(l, r, b, t);
  6868.         FrameRect(l - 1, r + 1, b - 1, t + 1);
  6869.     }
  6870.  
  6871.     /*Do the colors in the center*/
  6872.     
  6873.     rangeBot = b + 1;
  6874.     rangeTop = t - 1;
  6875.     diff = t - b - 2;
  6876.     if (diff > 0)
  6877.     {
  6878.         b = start = rangeBot;
  6879.         if (!numbersOnly)
  6880.         {
  6881.         for (k = 2; k < nColors - 1; ++k)
  6882.         {
  6883.             t = (k - 1) * diff / (nColors - 3) + start;
  6884.             if (rgbp)
  6885.             {
  6886.             c3s(colors[k]);
  6887.             }
  6888.             else
  6889.             {
  6890.             color(beg + k);
  6891.             }
  6892.             FillRect(l + 1, r - 1, b, t);
  6893.             b = t;
  6894.         }
  6895.         }
  6896.         SetObjectColor(textColor);
  6897.  
  6898.         r = l - 1;
  6899.         l = intLeft + stringWidth;
  6900.  
  6901.         /*Draw all the tics in the middle*/
  6902.         ddiff = minmax[1] - minmax[0];
  6903.         halfSpace = (ddiff) / (nColors - 4) * 0.5;
  6904.  
  6905.         CalcGoodSteps(ddiff,
  6906.               rangeTop - rangeBot,
  6907.               minMajorStep,
  6908.               &majorWidth, &nTics);
  6909.         minorWidth = majorWidth / nTics;
  6910.  
  6911.         /*Minor and major tics first*/
  6912.         temp = minmax[0] / majorWidth;
  6913.         curValue = temp * majorWidth;
  6914.  
  6915.         while (curValue > minmax[0])
  6916.         {
  6917.         curValue -= majorWidth;
  6918.         }
  6919.         k = 0;
  6920.         while (curValue < minmax[0])
  6921.         {
  6922.         ++k;
  6923.         if (k >= nTics) k = 0;
  6924.  
  6925.         curValue += minorWidth;
  6926.         }
  6927.  
  6928.         /*Now actually draw them*/
  6929.         if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  6930.         while (curValue <= minmax[1] + ddiff * 1.0E-6)
  6931.         {
  6932.         pixel = rangeBot + (curValue - minmax[0]) * (rangeTop - rangeBot) / (ddiff);
  6933.         if (k == 0)
  6934.         {
  6935.             /*Major tic*/
  6936.             if (numbersOnly)
  6937.             {
  6938.             sprintf(tempStr, "%lg", curValue);
  6939.             switch(alignment)
  6940.             {
  6941.                 case LEFTALIGN:
  6942.                 x = intLeft;
  6943.                 break;
  6944.                 case CENTERALIGN:
  6945.                 x = (intLeft + intRight - DSPPALETTESTL - StrWidth(tempStr)) / 2;
  6946.                 break;
  6947.                 case RIGHTALIGN:
  6948.                 x = intRight - DSPPALETTESTL - StrWidth(tempStr);
  6949.                 break;
  6950.             }
  6951.             }
  6952.             else
  6953.             {
  6954.             DrawLine(l, pixel, r, pixel);
  6955.             DrawLine(l, pixel + 1, r, pixel + 1);
  6956.             sprintf(tempStr, "%lg", curValue);
  6957.             switch(alignment)
  6958.             {
  6959.                 case LEFTALIGN:
  6960.                 x = intLeft;
  6961.                 break;
  6962.                 case CENTERALIGN:
  6963.                 x = (intLeft + l - DSPPALETTESTL) / 2;
  6964.                 break;
  6965.                 case RIGHTALIGN:
  6966.                 x = l - DSPPALETTESTL;
  6967.                 break;
  6968.             }
  6969.             }
  6970.             if (colorByPalette)
  6971.             {
  6972.             SetRealColor(curValue);
  6973.             }
  6974.             DrawAString(alignment, x, pixel - textSize / 2, tempStr);
  6975.             if (colorByPalette)
  6976.             {
  6977.             SetObjectColor(textColor);
  6978.             }
  6979.         }
  6980.         else if ((!numbersOnly) && drawMinorTics)
  6981.         {
  6982.             /*Minor tic*/
  6983.             DrawLine((l + r) / 2, pixel, r, pixel);
  6984.             DrawLine((l + r) / 2, pixel + 1, r, pixel + 1);
  6985.         }
  6986.  
  6987.         curValue += minorWidth;
  6988.         if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  6989.         ++k;
  6990.         if (k >= nTics) k = 0;
  6991.         }
  6992.     }
  6993.     }
  6994.     else
  6995.     {
  6996.     /*It's horizontal*/
  6997.     int rangeLeft, rangeRight;
  6998.     int x;
  6999.  
  7000.     minMajorStep *= 3;
  7001.     l = intLeft;
  7002.     r = intRight;
  7003.  
  7004.     boxWidth = (intRight - intLeft) * PALDISPLAYHCOLORWIDTH;
  7005.     boxHeight = (intTop - intBottom) * PALDISPLAYHCOLORHEIGHT;
  7006.  
  7007.     if (drawMissing)
  7008.     {
  7009.         /*Draw the missing data box*/
  7010.         r = l + boxWidth;
  7011.         if (numbersOnly)
  7012.         {
  7013.         b = intBottom;
  7014.         t = intTop;
  7015.         }
  7016.         else
  7017.         {
  7018.         t = intTop;
  7019.         b = t - boxHeight;
  7020.         FrameRect(l, r, b, t);
  7021.         FrameRect(l - 1, r + 1, b - 1, t + 1);
  7022.         if (rgbp)
  7023.         {
  7024.             c3s(colors[0]);
  7025.         }
  7026.         else
  7027.         {
  7028.             color(beg);
  7029.         }
  7030.         FillRect(l + 1, r - 1, b + 1, t - 1);
  7031.         SetObjectColor(textColor);
  7032.  
  7033.         b = intBottom + stringHeight;
  7034.         DrawLine((l + r) / 2, b, (l + r) / 2, t - boxHeight);
  7035.         DrawLine((l + r) / 2 + 1, b, (l + r) / 2 + 1, t - boxHeight);
  7036.         b = intBottom;
  7037.         }
  7038.         strcpy(tempStr, "Missing");
  7039.         switch(alignment)
  7040.         {
  7041.         case LEFTALIGN:
  7042.             x = (l + r) / 2;
  7043.             break;
  7044.         case CENTERALIGN:
  7045.             x = (l + r) / 2;
  7046.             break;
  7047.         case RIGHTALIGN:
  7048.             x = (l + r) / 2;
  7049.             break;
  7050.     
  7051.         }
  7052.         if (colorByPalette)
  7053.         {
  7054.         SetRealColor(missingData);
  7055.         }
  7056.         DrawAString(alignment, x, b, tempStr);
  7057.         if (colorByPalette)
  7058.         {
  7059.         SetObjectColor(textColor);
  7060.         }
  7061.  
  7062.         l = r + MINORBORDER;
  7063.         r = intRight;
  7064.     }
  7065.  
  7066.     if (drawOverUnder)
  7067.     {
  7068.         /*Draw the underflow data box*/
  7069.         r = l + boxWidth;
  7070.         if (numbersOnly)
  7071.         {
  7072.         b = intBottom;
  7073.         t = intTop;
  7074.         }
  7075.         else
  7076.         {
  7077.         t = intTop;
  7078.         b = t - boxHeight;
  7079.         FrameRect(l, r, b, t);
  7080.         FrameRect(l - 1, r + 1, b - 1, t + 1);
  7081.  
  7082.         if (rgbp)
  7083.         {
  7084.             c3s(colors[1]);
  7085.         }
  7086.         else
  7087.         {
  7088.             color(beg + 1);
  7089.         }
  7090.  
  7091.         FillRect(l + 1, r - 1, b + 1, t - 1);
  7092.         SetObjectColor(textColor);
  7093.  
  7094.         b = intBottom + stringHeight;
  7095.         DrawLine((l + r) / 2, b, (l + r) / 2, t - boxHeight);
  7096.         DrawLine((l + r) / 2 + 1, b, (l + r) / 2 + 1, t - boxHeight);
  7097.         b = intBottom;
  7098.         }
  7099.         strcpy(tempStr, "Under");
  7100.         switch(alignment)
  7101.         {
  7102.         case LEFTALIGN:
  7103.             x = (l + r) / 2;
  7104.             break;
  7105.         case CENTERALIGN:
  7106.             x = (l + r) / 2;
  7107.             break;
  7108.         case RIGHTALIGN:
  7109.             x = (l + r) / 2;
  7110.             break;
  7111.     
  7112.         }
  7113.         if (colorByPalette)
  7114.         {
  7115.         SetRealColor(MINUSINF);
  7116.         }
  7117.         DrawAString(alignment, x, b, tempStr);
  7118.         if (colorByPalette)
  7119.         {
  7120.         SetObjectColor(textColor);
  7121.         }
  7122.  
  7123.         l = r + MINORBORDER;
  7124.         r = intRight;
  7125.  
  7126.         /*Draw the overflow data box*/
  7127.         if (numbersOnly)
  7128.         {
  7129.         b = intBottom;
  7130.         t = intTop;
  7131.         }
  7132.         else
  7133.         {
  7134.         t = intTop;
  7135.         b = t - boxHeight;
  7136.         FrameRect(r - boxWidth, r, b, t);
  7137.         FrameRect(r - boxWidth - 1, r + 1, b - 1, t + 1);
  7138.         if (rgbp)
  7139.         {
  7140.         c3s(colors[nColors - 1]);
  7141.         }
  7142.         else
  7143.         {
  7144.         color(beg + nColors - 1);
  7145.         }
  7146.         FillRect(r - boxWidth + 1, r - 1, b + 1, t - 1);
  7147.         SetObjectColor(textColor);
  7148.  
  7149.         b = intBottom + stringHeight;
  7150.         DrawLine((r - boxWidth + r) / 2, b, (r - boxWidth + r) / 2, t - boxHeight);
  7151.         DrawLine((r - boxWidth + r) / 2 + 1, b, (r - boxWidth + r) / 2 + 1, t - boxHeight);
  7152.         b = intBottom;
  7153.         }
  7154.         strcpy(tempStr, "Over");
  7155.         switch(alignment)
  7156.         {
  7157.         case LEFTALIGN:
  7158.             x = (r - boxWidth + r) / 2;
  7159.             break;
  7160.         case CENTERALIGN:
  7161.             x = (r - boxWidth + r) / 2;
  7162.             break;
  7163.         case RIGHTALIGN:
  7164.             x = (r - boxWidth + r) / 2;
  7165.             break;
  7166.     
  7167.         }
  7168.         if (colorByPalette)
  7169.         {
  7170.         SetRealColor(PLUSINF);
  7171.         }
  7172.         DrawAString(alignment, x, b, tempStr);
  7173.         if (colorByPalette)
  7174.         {
  7175.         SetObjectColor(textColor);
  7176.         }
  7177.  
  7178.         r = intRight - boxWidth - MINORBORDER;
  7179.     }
  7180.  
  7181.     /*Draw the main section of the display*/
  7182.     t = intTop;
  7183.     b = t - boxHeight;
  7184.  
  7185.     if (!numbersOnly)
  7186.     {
  7187.         FrameRect(l, r, b, t);
  7188.         FrameRect(l - 1, r + 1, b - 1, t + 1);
  7189.     }
  7190.  
  7191.     /*Do the colors in the center*/
  7192.     
  7193.     rangeLeft = l + 1;
  7194.     rangeRight = r - 1;
  7195.     diff = r - l - 2;
  7196.     if (diff > 0)
  7197.     {
  7198.         l = start = rangeLeft;
  7199.         if (!numbersOnly)
  7200.         {
  7201.         for (k = 2; k < nColors - 1; ++k)
  7202.         {
  7203.             r = (k - 1) * diff / (nColors - 3) + start;
  7204.             if (rgbp)
  7205.             {
  7206.             c3s(colors[k]);
  7207.             }
  7208.             else
  7209.             {
  7210.             color(beg + k);
  7211.             }
  7212.             FillRect(l, r, b + 1, t - 1);
  7213.             l = r;
  7214.         }
  7215.         }
  7216.         SetObjectColor(textColor);
  7217.  
  7218.         t = b - 1;
  7219.         b = intBottom + stringHeight + 2;
  7220.  
  7221.         /*Draw all the tics in the middle*/
  7222.         ddiff = minmax[1] - minmax[0];
  7223.         halfSpace = (ddiff) / (nColors - 4) * 0.5;
  7224.  
  7225.         CalcGoodSteps(ddiff,
  7226.               rangeRight - rangeLeft,
  7227.               minMajorStep,
  7228.               &majorWidth, &nTics);
  7229.         minorWidth = majorWidth / nTics;
  7230.  
  7231.         /*Minor and major tics first*/
  7232.         temp = minmax[0] / majorWidth;
  7233.         curValue = temp * majorWidth;
  7234.  
  7235.         while (curValue > minmax[0])
  7236.         {
  7237.         curValue -= majorWidth;
  7238.         }
  7239.         k = 0;
  7240.         while (curValue < minmax[0])
  7241.         {
  7242.         ++k;
  7243.         if (k >= nTics) k = 0;
  7244.  
  7245.         curValue += minorWidth;
  7246.         }
  7247.  
  7248.         /*Now actually draw them*/
  7249.         if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  7250.         while (curValue <= minmax[1] + ddiff * 1.0E-6)
  7251.         {
  7252.         pixel = rangeLeft + (curValue - minmax[0]) * (rangeRight - rangeLeft) / (ddiff);
  7253.         if (k == 0)
  7254.         {
  7255.             /*Major tic*/
  7256.             if (numbersOnly)
  7257.             {
  7258.             sprintf(tempStr, "%lg", curValue);
  7259.             }
  7260.             else
  7261.             {
  7262.             DrawLine(pixel, b, pixel, t);
  7263.             DrawLine(pixel + 1, b, pixel + 1, t);
  7264.             sprintf(tempStr, "%lg", curValue);
  7265.             }
  7266.             if (colorByPalette)
  7267.             {
  7268.             SetRealColor(curValue);
  7269.             }
  7270.             DrawAString(alignment, pixel, intBottom, tempStr);
  7271.             if (colorByPalette)
  7272.             {
  7273.             SetObjectColor(textColor);
  7274.             }
  7275.         }
  7276.         else if ((!numbersOnly) && drawMinorTics)
  7277.         {
  7278.             /*Minor tic*/
  7279.             DrawLine(pixel, (t + b) / 2, pixel, t);
  7280.             DrawLine(pixel + 1, (t + b) / 2, pixel + 1, t);
  7281.         }
  7282.  
  7283.         curValue += minorWidth;
  7284.         if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
  7285.         ++k;
  7286.         if (k >= nTics) k = 0;
  7287.         }
  7288.     }
  7289.     }
  7290.  
  7291.     if (IsSelected(display))
  7292.     {
  7293.     int horCent = (left + right)/2;
  7294.     int vertCent = (bottom + top)/2;
  7295.  
  7296.     /* Draw incredibly fancy frame for moving and resizing palette display */
  7297.     FrameUIWideRect(left+INSET, right-INSET,
  7298.             bottom+INSET, top-INSET,
  7299.                 OUTSIDEFRAMEWEIGHT, OUTSIDEFRAMECOLOR);
  7300.     FrameUIWideRect(left+INSET+OUTSIDEFRAMEWEIGHT,
  7301.             right-INSET-OUTSIDEFRAMEWEIGHT,
  7302.             bottom+INSET+OUTSIDEFRAMEWEIGHT,
  7303.             top-INSET-OUTSIDEFRAMEWEIGHT,
  7304.             INSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7305.     FrameUIWideRect(left+INSET+OUTSIDEFRAMEWEIGHT+INSIDEFRAMEWEIGHT,
  7306.             right-INSET-OUTSIDEFRAMEWEIGHT-INSIDEFRAMEWEIGHT,
  7307.             bottom+INSET+OUTSIDEFRAMEWEIGHT+INSIDEFRAMEWEIGHT,
  7308.             top-INSET-OUTSIDEFRAMEWEIGHT-INSIDEFRAMEWEIGHT,
  7309.             OUTSIDEFRAMEWEIGHT, OUTSIDEFRAMECOLOR);
  7310.  
  7311.     /* Now draw the handles */
  7312.     /* center of sides */
  7313.     FillUIRect(left, left+HANDLESIZE,
  7314.             vertCent-HANDLESIZE/2, vertCent+HANDLESIZE/2, OUTSIDEFRAMECOLOR);
  7315.     FillUIRect(left+OUTSIDEFRAMEWEIGHT,
  7316.             left+HANDLESIZE-OUTSIDEFRAMEWEIGHT,
  7317.             vertCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
  7318.             vertCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7319.  
  7320.     FillUIRect(right-HANDLESIZE, right,
  7321.             vertCent-HANDLESIZE/2, vertCent+HANDLESIZE/2, OUTSIDEFRAMECOLOR);
  7322.     FillUIRect(right-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
  7323.             right-OUTSIDEFRAMEWEIGHT,
  7324.             vertCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
  7325.             vertCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7326.  
  7327.     /* top edge */
  7328.     FillUIRect(horCent-HANDLESIZE/2, horCent+HANDLESIZE/2,
  7329.             top-HANDLESIZE, top, OUTSIDEFRAMECOLOR);
  7330.     FillUIRect(horCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
  7331.             horCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT,
  7332.             top-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
  7333.             top-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7334.  
  7335.     FillUIRect(left, left+HANDLESIZE,
  7336.             top-HANDLESIZE, top, OUTSIDEFRAMECOLOR);
  7337.     FillUIRect(left+OUTSIDEFRAMEWEIGHT,
  7338.             left+HANDLESIZE-OUTSIDEFRAMEWEIGHT,
  7339.             top-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
  7340.             top-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7341.         
  7342.     FillUIRect(right-HANDLESIZE, right,
  7343.             top-HANDLESIZE, top, OUTSIDEFRAMECOLOR);
  7344.     FillUIRect(right-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
  7345.             right-OUTSIDEFRAMEWEIGHT,
  7346.             top-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
  7347.             top-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7348.  
  7349.     /* bottom edge */
  7350.     FillUIRect(horCent-HANDLESIZE/2, horCent+HANDLESIZE/2,
  7351.             bottom, bottom+HANDLESIZE, OUTSIDEFRAMECOLOR);
  7352.     FillUIRect(horCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
  7353.             horCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT,
  7354.             bottom+OUTSIDEFRAMEWEIGHT,
  7355.             bottom+HANDLESIZE-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7356.  
  7357.     FillUIRect(left, left+HANDLESIZE,
  7358.             bottom, bottom+HANDLESIZE, OUTSIDEFRAMECOLOR);
  7359.     FillUIRect(left+OUTSIDEFRAMEWEIGHT,
  7360.             left+HANDLESIZE-OUTSIDEFRAMEWEIGHT,
  7361.             bottom+OUTSIDEFRAMEWEIGHT,
  7362.             bottom+HANDLESIZE-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7363.         
  7364.     FillUIRect(right-HANDLESIZE, right,
  7365.             bottom, bottom+HANDLESIZE, OUTSIDEFRAMECOLOR);
  7366.     FillUIRect(right-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
  7367.             right-OUTSIDEFRAMEWEIGHT,
  7368.             bottom+OUTSIDEFRAMEWEIGHT,
  7369.             bottom+HANDLESIZE-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
  7370.     }
  7371. #endif
  7372.     return ObjTrue;
  7373. }
  7374.  
  7375. ObjPtr SelectPaletteDisplay(object, selectp)
  7376. ObjPtr object;
  7377. Bool selectp;
  7378. /*Selects an icon*/
  7379. {
  7380.     if (selectp)
  7381.     {
  7382.     MakeMeCurrent(object);
  7383.     }
  7384.  
  7385.     ImInvalid(object);
  7386.     return ObjTrue;
  7387. }
  7388.  
  7389. #define PDPICKSLOP 10
  7390.  
  7391. static ObjPtr PressPaletteDisplay(display, mouseX, mouseY, flags)
  7392. ObjPtr display;
  7393. int mouseX, mouseY;
  7394. long flags;
  7395. {
  7396. #ifdef INTERACTIVE
  7397.     int left, right, bottom, top, hCent, vCent;
  7398.     Bool ml, mr, mb, mt;
  7399.     int mX, mY;
  7400.     ObjPtr var, palette;
  7401.  
  7402.     Get2DIntBounds(display, &left, &right, &bottom, &top);
  7403.  
  7404.     /* return if mouse outside text box */
  7405.     if (mouseX < left || mouseX > right || mouseY < bottom 
  7406.     || mouseY > top) return ObjFalse;
  7407.  
  7408.     if (TOOL(flags) == T_HELP) /* help mode? */
  7409.     {
  7410.     ContextHelp(display);
  7411.     return ObjTrue;
  7412.     }
  7413.  
  7414.     MakeMeCurrent(display);
  7415.  
  7416.     hCent = (left + right)/2;
  7417.     vCent = (bottom + top)/2;
  7418.  
  7419.     ml = mr = mb = mt = false;
  7420.  
  7421.     if (mouseX < left + HANDLESIZE) /* on left side */
  7422.     {
  7423.     if (mouseY > top - HANDLESIZE) /* top-left handle */
  7424.         mt = ml = true;
  7425.     else if (mouseY < bottom + HANDLESIZE) /* bottom-left handle */
  7426.         mb = ml = true;
  7427.     else if (mouseY > vCent - HANDLESIZE/2 && mouseY < vCent + HANDLESIZE/2)
  7428.         ml = true; /* bottom middle handle */
  7429.     else ml = mr = mb = mt = true; /* in frame */
  7430.     }
  7431.     else if (mouseX > right - HANDLESIZE) /* on right side */
  7432.     {
  7433.     if (mouseY > top - HANDLESIZE) /* top-right handle */
  7434.         mt = mr = true;
  7435.     else if (mouseY < bottom + HANDLESIZE) /* bottom-right handle */
  7436.         mb = mr = true;
  7437.     else if (mouseY > vCent - HANDLESIZE/2 && mouseY < vCent + HANDLESIZE/2)
  7438.         mr = true;
  7439.     else ml = mr = mb = mt = true; /* in frame */
  7440.     }
  7441.     else if (mouseY < bottom + HANDLESIZE) /* on bottom */
  7442.     {
  7443.     /* already handled (heh heh) corners */
  7444.     if (mouseX > hCent - HANDLESIZE/2 && mouseX < hCent + HANDLESIZE/2)
  7445.         mb = true; /* bottom middle handle */
  7446.     else ml = mr = mb = mt = true; /* in frame */
  7447.     }
  7448.     else if (mouseY > top - HANDLESIZE) /* on top */
  7449.     {
  7450.     /* already handled (heh heh) corners */
  7451.     if (mouseX > hCent - HANDLESIZE/2 && mouseX < hCent + HANDLESIZE/2)
  7452.         mt = true; /* middle top handle */
  7453.     else ml = mr = mb = mt = true; /* in frame */
  7454.     }
  7455.  
  7456.     {
  7457.         if (!(flags & F_EXTEND) && !IsSelected(display))
  7458.         {
  7459.         /*It's a new selection and not already selected.  Deselect the
  7460.           rest*/
  7461.         DeselectAll();
  7462.         }
  7463.  
  7464.         if ((flags & F_EXTEND) && IsSelected(display))
  7465.         {
  7466.         /*Deselect*/
  7467.         Select(display, false);
  7468.         return ObjTrue;
  7469.         }
  7470.         else if (!IsSelected(display))
  7471.         {
  7472.         /*Must select it*/
  7473.         
  7474.         Select(display, true);
  7475.         DrawMe(display);
  7476.         UpdateDrawing();
  7477.         }
  7478.     }
  7479.  
  7480.     if (mr || ml || mb || mt) /* drag the incredibly fancy frame around */
  7481.     {
  7482.     /* I am greatly indebted to my friend and colleague, Eric Pepke,
  7483.        for the following code. Any errors or obfuscations are his. */
  7484.     /*Oh yeah?  Well, I stole it back!  So now the bugs are yours!*/
  7485.     int initX = mouseX, initY = mouseY;
  7486.     int newLeft, newRight, newBottom, newTop;
  7487.     int oldNewLeft, oldNewRight, oldNewBottom, oldNewTop;
  7488.  
  7489.     SaveForUndo(display);
  7490.  
  7491.     newLeft = oldNewLeft = left;
  7492.     newRight = oldNewRight = right;
  7493.     newBottom = oldNewBottom = bottom;
  7494.     newTop = oldNewTop = top;
  7495.  
  7496.     while (Mouse(&mX, &mY))
  7497.     {
  7498.         if (ml) newLeft = left + mX - initX;
  7499.         if (mr) newRight = right + mX - initX;
  7500.         if (mb) newBottom = bottom + mY - initY;
  7501.         if (mt) newTop = top + mY - initY;
  7502.  
  7503.         if (flags & F_SHIFTDOWN)
  7504.         {
  7505.         /*Grid drag*/
  7506.         if (ml && mr && mb && mt)
  7507.         {
  7508.             /*Special case--whole object gridded
  7509.             Only grid top left*/
  7510.             int width, height;
  7511.             width = newRight - newLeft;
  7512.             height = newTop - newBottom;
  7513.             newLeft = GRIDX(newLeft);
  7514.             newRight = newLeft + width;
  7515.             newTop = top - (GRIDY(top - newTop));
  7516.             newBottom = newTop - height;
  7517.         }
  7518.         else
  7519.         {
  7520.             /*Normal case*/
  7521.             if (ml) newLeft = GRIDX(newLeft);
  7522.             if (mr) newRight = right - GRIDX(right - newRight);
  7523.             if (mb) newBottom = GRIDY(newBottom);
  7524.             if (mt) newTop = top - GRIDY(top - newTop);
  7525.         }
  7526.         }
  7527.         if (ml && newLeft + 3 * HANDLESIZE > newRight)
  7528.         newLeft = newRight - 3 * HANDLESIZE;
  7529.         if (mr && newLeft + 3 * HANDLESIZE > newRight)
  7530.         newRight = newLeft + 3 * HANDLESIZE;
  7531.         if (mb && newBottom + 3 * HANDLESIZE > newTop)
  7532.         newBottom = newTop - 3 * HANDLESIZE;
  7533.         if (mt && newBottom + 3 * HANDLESIZE > newTop)
  7534.         newTop = newBottom + 3 * HANDLESIZE;
  7535.         if ((newLeft != oldNewLeft ||
  7536.          newRight != oldNewRight ||
  7537.          newBottom != oldNewBottom ||
  7538.          newTop != oldNewTop) &&
  7539.          newLeft < newRight &&
  7540.          newBottom < newTop)
  7541.         {
  7542.         Set2DIntBounds(display, newLeft, newRight, newBottom, newTop);
  7543.         oldNewLeft = newLeft;
  7544.         oldNewRight = newRight;
  7545.         oldNewBottom = newBottom;
  7546.         oldNewTop = newTop;
  7547.         DrawMe(display);
  7548.         }
  7549.     }
  7550.     if (logging)
  7551.     {
  7552.         char cmd[256];
  7553.         MakeObjectName(tempStr, display);
  7554.         sprintf(cmd, "set bounds %s [%d %d %d %d]\n",
  7555.             tempStr, newLeft, newRight,
  7556.             newBottom, newTop);
  7557.         Log(cmd);
  7558.     }
  7559.     }
  7560.     return ObjTrue;
  7561. #else
  7562.     return ObjFalse;
  7563. #endif
  7564. }
  7565.  
  7566. #ifdef PROTO
  7567. ObjPtr NewPaletteDisplay(int left, int right, int bottom, int top, char *name, ObjPtr palette)
  7568. #else
  7569. ObjPtr NewPaletteDisplay(left, right, bottom, top, name, palette)
  7570. int left, right, bottom, top;
  7571. char *name;
  7572. ObjPtr palette;
  7573. #endif
  7574. /*Makes a new palette display*/
  7575. {
  7576.     ObjPtr retVal;
  7577.     retVal = NewObject(paletteDisplayClass, 0);
  7578.     if (!retVal)
  7579.     {
  7580.     return NULLOBJ;
  7581.     }
  7582.  
  7583.     Set2DIntBounds(retVal, left, right, bottom, top);
  7584.     SetVar(retVal, NAME, NewString(name));
  7585.     SetVar(retVal, REPOBJ, palette);
  7586.  
  7587.     return retVal;
  7588. }
  7589.  
  7590. ObjPtr CompleteSavePalette(palette, whichButton)
  7591. ObjPtr palette;
  7592. int whichButton;
  7593. /*Completes a "save palette" operation*/
  7594. {
  7595.     SaveObjectControls(palette, GetVar(palette, DIRECTORY));
  7596.     return ObjTrue;
  7597. }
  7598.  
  7599. ObjPtr SavePalette(palette)
  7600. ObjPtr palette;
  7601. /*Asks for a palette to be saved*/
  7602. {
  7603.     ObjPtr name, directory;
  7604.     char *s, nameStr[401];
  7605.  
  7606.     name = GetStringVar("SavePalette", palette, NAME);
  7607.     if (!name)
  7608.     {
  7609.     return ObjFalse;
  7610.     }
  7611.  
  7612.     strcpy(nameStr, GetString(name));
  7613.     s = nameStr;
  7614.     while (*s) ++s;
  7615.  
  7616.     while (*s != ' ') --s;
  7617.     *s = 0;
  7618.  
  7619.     directory = GetVar(palette, DIRECTORY);
  7620.  
  7621.     if (directory)
  7622.     {
  7623.     sprintf(tempStr, "Save this palette for datasets named %s in directory %s?",
  7624.         nameStr, GetString(directory));
  7625.     }
  7626.     else
  7627.     {
  7628.     sprintf(tempStr, "Save this palette for datasets named %s in the current directory?",
  7629.         nameStr);
  7630.     }
  7631.     AlertUser(UICAUTIONALERT, (WinInfoPtr) palette, tempStr, CompleteSavePalette, 2, "Save", "Cancel");
  7632.  
  7633.     return ObjTrue;
  7634. }
  7635.  
  7636. ObjPtr SavePaletteControls(palette)
  7637. ObjPtr palette;
  7638. /*Saves a palette by logging all palette controls*/
  7639. {
  7640.     int k;
  7641.     ObjPtr var;
  7642.     real *minmax;
  7643.     int nColors;
  7644.     short3 *colors;
  7645.  
  7646.     var = GetFixedArrayVar("SavePaletteControls", palette, MINMAX, 1, 2L);
  7647.     if (!var)
  7648.     {
  7649.     return ObjFalse;
  7650.     }
  7651.     minmax = ELEMENTS(var);
  7652.  
  7653.     var = GetIntVar("SavePaletteControls", palette, NCOLORS);
  7654.     if (!var)
  7655.     {
  7656.     return ObjFalse;
  7657.     }
  7658.     nColors = GetInt(var);
  7659.  
  7660.     sprintf(tempStr, "set value Field\\ Max \"%g\"\n", minmax[1]);
  7661.     Log(tempStr);
  7662.     sprintf(tempStr, "set value Field\\ Min \"%g\"\n", minmax[0]);
  7663.     Log(tempStr);
  7664.     sprintf(tempStr, "set value N\\ Colors \"%d\"\n", nColors);
  7665.     Log(tempStr);
  7666.  
  7667.     MakeVar(palette, COLORS);
  7668.     var = GetVar(palette, COLORS);
  7669.     if (!var)
  7670.     {
  7671.     return ObjFalse;
  7672.     }
  7673.     colors = ELEMENTS(var);
  7674.  
  7675.     for (k = 0; k < nColors; ++k)
  7676.     {
  7677.     sprintf(tempStr, "set color Palette\\ Colors %d %d %d %d\n",
  7678.         k,  colors[k][0], colors[k][1], colors[k][2]);
  7679.     Log(tempStr);
  7680.     }
  7681.     return ObjTrue;
  7682. }
  7683.  
  7684. static ObjPtr MakeColorBarAppearance(colorBar)
  7685. ObjPtr colorBar;
  7686. /*Makes an object's appearance*/
  7687. {
  7688.     ImInvalid(colorBar);
  7689.     SetVar(colorBar, APPEARANCE, ObjTrue);
  7690.     return ObjTrue;
  7691. }
  7692.  
  7693. static ObjPtr MakePaletteColors(palette)
  7694. ObjPtr palette;
  7695. /*Makes a palette's colors.  May have to resample if the number of colors has
  7696.   changed.*/
  7697. {
  7698.     ObjPtr colors, newColors;
  7699.     ObjPtr var;
  7700.     long nColors;
  7701.  
  7702.     colors = GetVar(palette, COLORS);
  7703.     if (!colors)
  7704.     {
  7705.     return ObjFalse;
  7706.     }
  7707.     
  7708.     MakeVar(palette, NCOLORS);
  7709.     var = GetIntVar("MakePaletteColors", palette, NCOLORS);
  7710.     if (!var)
  7711.     {
  7712.     return ObjFalse;
  7713.     }
  7714.     nColors = GetInt(var);
  7715.  
  7716.     if (nColors != DIMS(colors)[0])
  7717.     {
  7718.     /*Need to resample*/
  7719.  
  7720.     SetPaletteNColors(palette, nColors);
  7721.     }
  7722.     else
  7723.     {
  7724.     SetVar(palette, COLORS, GetVar(palette, COLORS));
  7725.     }
  7726.     return ObjTrue;
  7727. }
  7728.  
  7729. static ObjPtr MakePaletteChanged(palette)
  7730. ObjPtr palette;
  7731. /*Makes a palette changed*/
  7732. {
  7733.     SetVar(palette, CHANGED, ObjTrue);
  7734.     return ObjTrue;
  7735. }
  7736.  
  7737. void InitColors()
  7738. /*Initialize the color system*/
  7739. {
  7740.     int k;
  7741.     int colorBeg, colorEnd;
  7742.     ObjPtr var;
  7743.     ObjPtr list;
  7744.  
  7745.     iconColorPalette = NewIcon(0, 0, ICONCTABLE, "Color Palette");
  7746.     AddToReferenceList(iconColorPalette);
  7747.  
  7748.     /*Make a color palette class*/
  7749.     paletteClass = NewObject(NULLOBJ, sizeof(Palette) - sizeof(Thing));
  7750.     AddToReferenceList(paletteClass);
  7751.     SETOBJTYPE(paletteClass -> flags, PALETTE);
  7752.     SetVar(paletteClass, COLORCOMP, NULLOBJ);
  7753.     SetVar(paletteClass, BEGCOLOR, NULLOBJ);
  7754.     SetVar(paletteClass, NCOLORS, NewInt(0));
  7755.     SetVar(paletteClass, DEFAULTICON, iconColorPalette);
  7756.     SetVar(paletteClass, COLORMODEL, NewInt(CM_RGB));
  7757.     SetMethod(paletteClass, EDITPALETTE, NewControlWindow);
  7758.     SetVar(paletteClass, DOUBLECLICK, NewString(OF_SHOW_CONTROLS));
  7759.     SetMethod(paletteClass, NAME, MakePaletteName);
  7760.     SetMethod(paletteClass, CLONE, ClonePalette);
  7761.     SetMethod(paletteClass, CLEANUP, CleanupPalette);
  7762.     SetMethod(paletteClass, NEWCTLWINDOW, ShowPaletteControls);
  7763.     SetMethod(paletteClass, SHOWCONTROLS, NewControlWindow);
  7764.     SetVar(paletteClass, SAVEEXTENSION, NewString("pal"));
  7765.     SetMethod(paletteClass, SAVECPANEL, SavePalette);
  7766.     SetMethod(paletteClass, SAVEALLCONTROLS, SavePaletteControls);
  7767.     SetMethod(paletteClass, LOCALCOPY, MakeLocalCopy);
  7768.     DeclareDependency(paletteClass, CHANGED, COLORS);
  7769.     DeclareDependency(paletteClass, CHANGED, MINMAX);
  7770.     SetMethod(paletteClass, CHANGED, MakePaletteChanged);
  7771.     DeclareDependency(paletteClass, COLORS, NCOLORS);
  7772.     SetMethod(paletteClass, COLORS, MakePaletteColors);
  7773.     SetMethod(paletteClass, REVERT, RevertPalette);
  7774.     SetMethod(paletteClass, KEEP, KeepPalette);
  7775.     SetMethod(paletteClass, TORGB, ToRGB);
  7776.     SetMethod(paletteClass, TOYIQ, ToYIQ);
  7777.     SetMethod(paletteClass, TOHSV, ToHSV);
  7778.     SetMethod(paletteClass, TOHLS, ToHLS);
  7779.     var = NewRealArray(1, 2L);
  7780.     ((real *) ELEMENTS(var))[0] = 0.0;
  7781.     ((real *) ELEMENTS(var))[1] = 1.0;
  7782.     SetVar(paletteClass, MINMAX, var);
  7783.  
  7784. #ifdef GRAPHICS
  7785.     /*If there is a cmap mode, figure out the number of colors*/
  7786.     if (hasCmap)
  7787.     {
  7788.     char *nColorsString;
  7789.     char *colorBegString;
  7790.     colorEnd = 1;
  7791.     for (k = 0; k < cmapBitPlanes; ++k)
  7792.     {
  7793.         colorEnd *= 2;
  7794.     }
  7795.  
  7796.     /*Trim off the top 512 if it's too big for the GTX version*/
  7797.     if (colorEnd >= 4096)
  7798.     {
  7799.         colorEnd -= 512;
  7800.     }
  7801.  
  7802.     /*Determine beginning based on end*/
  7803.     if (colorEnd <= 512)
  7804.     {
  7805.         colorBeg = COLORBEG8BITS;
  7806.     }
  7807.     else
  7808.     {
  7809.         colorBeg = COLORBEGMOREBITS;
  7810.     }
  7811.  
  7812.     if (colorBegString = getenv("SCIAN_COLOR_BEG"))
  7813.     {
  7814.         int temp;
  7815.         if (1 == sscanf(colorBegString, "%d", &temp))
  7816.         {
  7817.         colorBeg = temp;
  7818.         if (showConfig)
  7819.         fprintf(stderr, "Color beginning overridden to %d\n", temp);
  7820.         }
  7821.         else
  7822.         {
  7823.         fprintf(stderr, "Bad color beginning: %s\n", colorBegString);
  7824.         }
  7825.     }
  7826.  
  7827.     if (nColorsString = getenv("SCIAN_N_COLORS"))
  7828.     {
  7829.         int nColors;
  7830.         if (1 == sscanf(nColorsString, "%d", &nColors))
  7831.         {
  7832.         colorEnd = colorBeg + nColors;
  7833.         if (showConfig)
  7834.         printf("Number of colors overridden to be %d\n", nColors);
  7835.         }
  7836.         else
  7837.         {
  7838.         fprintf(stderr, "Bad value for environment variable SCIAN_NCOLORS: %s\n", nColorsString);
  7839.         }
  7840.     }
  7841.  
  7842.     if (showConfig)
  7843.     {
  7844.         printf("Visualization colors from %d to %d\n", colorBeg, colorEnd);
  7845.     }
  7846.  
  7847.     curUIColorIndex = colorBeg;
  7848.  
  7849. #ifdef RELEASE
  7850.     nScavengeColors = colorBeg;
  7851. #else
  7852.     nScavengeColors = 256;
  7853. #endif
  7854.     }
  7855.  
  7856.     if (hasCmap && scavengeColors)
  7857.     {
  7858.     Colorindex i;
  7859.  
  7860.     nScavengeColors = colorBeg;
  7861.     colorsToScavenge = (short3 *) Alloc(nScavengeColors * sizeof(short3));
  7862.     if (!colorsToScavenge)
  7863.     {
  7864.         nScavengeColors = 0;
  7865.     }
  7866.  
  7867.     /*Load up the scavenged colors*/
  7868.     for (i = 0; i < nScavengeColors; ++i)
  7869.     {
  7870.         getmcolor(i, 
  7871.         &(colorsToScavenge[i][0]),
  7872.         &(colorsToScavenge[i][1]),
  7873.         &(colorsToScavenge[i][2]));
  7874.     }
  7875.     }
  7876.     else
  7877.     {
  7878.     nScavengeColors = 0;
  7879.     colorsToScavenge = 0;
  7880.     }
  7881.  
  7882.     /*Initialize user interface colors*/
  7883.     MakeUIColor(UIBLACK, 0, 0, 0);
  7884.     MakeUIColor(UIGRAY12, 30, 30, 30);
  7885.     MakeUIColor(UIGRAY25, 61, 61, 61);
  7886.     MakeUIColor(UIGRAY37, 95, 95, 95);
  7887.     MakeUIColor(UIGRAY50, 128, 128, 128);
  7888.     MakeUIColor(UIGRAY62, 163, 163, 163);
  7889.     MakeUIColor(UIGRAY75, 193, 193, 193);
  7890.     MakeUIColor(UIGRAY87, 224, 224, 224);
  7891.     MakeUIColor(UIWHITE, 255, 255, 255);
  7892.  
  7893.     MakeUIColor(UIRED, 225, 0, 0);
  7894.     MakeUIColor(UIGREEN, 0, 225, 0);
  7895.     MakeUIColor(UIBLUE, 0, 0, 225);
  7896.     MakeUIColor(UIMAGENTA, 225, 0, 225);
  7897.     MakeUIColor(UIYELLOW, 245, 245, 0);
  7898.     MakeUIColor(UICYAN, 0, 225, 225);
  7899.     MakeUIColor(UIGOLD, 247, 188, 0);
  7900.  
  7901.     MakeUIColor(UIPRED, 182, 128, 128);
  7902.     MakeUIColor(UIPGREEN, 128, 171, 128);
  7903.     MakeUIColor(UIPBLUE, 128, 145, 171);
  7904.     MakeUIColor(UIPMAGENTA, 171, 128, 171);
  7905.     MakeUIColor(UIPYELLOW, 171, 171, 128);
  7906.     MakeUIColor(UIPCYAN, 128, 171, 171);
  7907.  
  7908.     if (colorsToScavenge)
  7909.     {
  7910.     Free(colorsToScavenge);
  7911.     colorsToScavenge = 0;
  7912.     }
  7913.  
  7914.     /*Now colorBeg set to be above NUICOLORS*/
  7915.     if (hasCmap)
  7916.     {
  7917.     colorBeg = curUIColorIndex; 
  7918.  
  7919.     /*Make first color range*/
  7920.     colorRanges = newp(ColorRange);
  7921.     colorRanges -> beg = colorBeg;
  7922.     colorRanges -> end = colorEnd;
  7923.     colorRanges -> next = (ColorRange *) 0;
  7924.     }
  7925.     else
  7926.     {
  7927.     colorRanges = 0;
  7928.     }
  7929. #endif
  7930.  
  7931.     colorControlClass = NewObject(controlClass, 0);
  7932.     AddToReferenceList(colorControlClass);
  7933.  
  7934.     colorWheelClass = NewObject(colorControlClass, 0);
  7935.     AddToReferenceList(colorWheelClass);
  7936. #ifdef GRAPHICS
  7937.     SetMethod(colorWheelClass, DRAW, DrawColorWheel);
  7938. #endif
  7939. #ifdef INTERACTIVE
  7940.     SetMethod(colorWheelClass, PRESS, PressColorWheel);
  7941. #endif
  7942.     SetMethod(colorWheelClass, SETVAL, SetColorWheelVal);
  7943.     SetVar(colorWheelClass, TYPESTRING, NewString("color wheel"));
  7944.     SetVar(colorWheelClass, HELPSTRING, NewString("To select a color, click at the color you desire.  \
  7945. Colors around the edge of the circle are fully saturated; colors near the center are \
  7946. less saturated.  Hold down the Shift key while pressing to \
  7947. constrain to full or half saturation.  Double-click to snap to the closest full- or half-saturated \
  7948. color or white.")); 
  7949.  
  7950.     /*Create a color bar class*/
  7951.     colorBarClass = NewObject(controlClass, 0);
  7952.     AddToReferenceList(colorBarClass);
  7953. #ifdef GRAPHICS
  7954.     SetMethod(colorBarClass, DRAW, DrawColorBar);
  7955. #endif
  7956. #ifdef INTERACTIVE
  7957.     SetMethod(colorBarClass, PRESS, PressColorBar);
  7958. #endif
  7959.     SetVar(colorBarClass, OPAQUE, ObjTrue);
  7960.     SetMethod(colorBarClass, SETVAL, SetColorBarVal);
  7961.     DeclareIndirectDependency(colorBarClass, APPEARANCE, REPOBJ, COLORS);
  7962.     DeclareIndirectDependency(colorBarClass, APPEARANCE, REPOBJ, MINMAX);
  7963.     SetMethod(colorBarClass, APPEARANCE, MakeColorBarAppearance);
  7964.  
  7965.     /*Create a palette display class*/
  7966.     paletteDisplayClass = NewObject(controlClass, 0);
  7967.     AddToReferenceList(paletteDisplayClass);
  7968.     SetVar(paletteDisplayClass, SHOWMINORTICS, ObjTrue);
  7969. #ifdef GRAPHICS
  7970.     SetMethod(paletteDisplayClass, DRAW, DrawPaletteDisplay);
  7971. #endif
  7972. #ifdef INTERACTIVE
  7973.     SetMethod(paletteDisplayClass, PRESS, PressPaletteDisplay);
  7974. #endif
  7975.     SetMethod(paletteDisplayClass, NEWCTLWINDOW, ShowPaletteDisplayControls);
  7976.     SetMethod(paletteDisplayClass, SHOWCONTROLS, NewControlWindow);
  7977.     SetMethod(paletteDisplayClass, ALIGNLEFT, AlignLeft);
  7978.     SetMethod(paletteDisplayClass, ALIGNCENTER, AlignCenter);
  7979.     SetMethod(paletteDisplayClass, ALIGNRIGHT, AlignRight);
  7980.     SetMethod(paletteDisplayClass, SETTEXTSIZE, SetTextSizeMethod);
  7981.     SetMethod(paletteDisplayClass, SETTEXTFONT, SetTextFontMethod);
  7982.  
  7983.     /*Make list of snapshot variables*/
  7984.     list = NewList();
  7985.     PrefixList(list, NewSymbol(BOUNDS));
  7986.     PrefixList(list, NewSymbol(TEXTFONT));
  7987.     PrefixList(list, NewSymbol(TEXTSIZE));
  7988.     PrefixList(list, NewSymbol(ALIGNMENT));
  7989.     SetVar(paletteDisplayClass, SNAPVARS, list);
  7990.  
  7991.     var = NewRealArray(1, 3L);
  7992.     ((real *) ELEMENTS(var))[0] = 1.0;
  7993.     ((real *) ELEMENTS(var))[1] = 1.0;
  7994.     ((real *) ELEMENTS(var))[2] = 1.0;
  7995.     SetVar(paletteDisplayClass, COLOR, var);
  7996.     SetTextFont(paletteDisplayClass, DSPPALETTEFONT);
  7997.     SetTextSize(paletteDisplayClass, DSPPALETTESIZE);
  7998.     SetMethod(paletteDisplayClass, SELECT, SelectPaletteDisplay);
  7999.     SetTextAlign(paletteDisplayClass, RIGHTALIGN);
  8000.     SetVar(paletteDisplayClass, MINMAJORSTEP, NewInt(30));
  8001. }
  8002.  
  8003. void KillColors()
  8004. {
  8005.     DeleteThing(paletteDisplayClass);
  8006.     DeleteThing(colorBarClass);
  8007.     DeleteThing(colorWheelClass);
  8008.     DeleteThing(colorControlClass);
  8009.     DeleteThing(paletteClass);
  8010.     DeleteThing(iconColorPalette);
  8011. }
  8012.